<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Automation – IMG.LY Blog</title><description>Posts tagged Automation on the IMG.LY blog.</description><link>https://img.ly/blog/tag/automation/</link><language>en-us</language><image><url>https://img.ly/apple-touch-icon.png</url><title>Automation – IMG.LY Blog</title><link>https://img.ly/blog/tag/automation/</link></image><atom:link href="https://img.ly/blog/tag/automation/rss.xml" rel="self" type="application/rss+xml"/><generator>Astro</generator><lastBuildDate>Fri, 12 Jun 2026 10:11:07 GMT</lastBuildDate><ttl>60</ttl><item><title>Javascript Video Editing: Ultimate Guide for Developers and PMs</title><link>https://img.ly/blog/javascript-video-editing-guide/</link><guid isPermaLink="true">https://img.ly/blog/javascript-video-editing-guide/</guid><description>A comprehensive guide to JavaScript video editing for developers and PMs. Learn about essential features, modern web technologies, and common tools like FFmpeg.js and IMG.LY&apos;s CE.SDK to create powerful web-based video editors.</description><pubDate>Fri, 20 Dec 2024 14:06:55 GMT</pubDate><content:encoded>&lt;p&gt;When developing or integrating a JavaScript-based video editor for the web, you must consider a number of factors to ensure the solution is both efficient and robust. This post is the definitive guide for anyone embarking on such a project. It explores the key technologies involved, their strengths and weaknesses, and how different use cases influence the choice of tech stack. We’ll examine diverse use cases, from lightweight, browser-based editors for quick edits to more advanced tools requiring complex processing and rendering. We’ll then discuss how these scenarios drive the selection of features and technology.&lt;/p&gt;
&lt;p&gt;Additionally, we will show you the best open-source solutions that can accelerate development. This technical analysis will help you make an informed “build vs. buy” decision, ensuring you select the right approach for your project. Throughout this post, we will use the example of the IMG.LY’s JavaScript video editor (see &lt;a href=&quot;https://img.ly/showcases/cesdk/video-ui/web&quot;&gt;here for a demo&lt;/a&gt;), showing you how these considerations shaped its architecture and feature set. You will learn practical insights into the decision-making process behind a successful web-based video editor.&lt;/p&gt;
&lt;p&gt;Modern web technologies like WebGL, WebCodecs and WebAssembly have enabled browsers to efficiently perform resource-intensive tasks such as video editing that had hitherto been the sole domain of desktop applications. As a result Javascript based video editing tools such as &lt;a href=&quot;https://www.veed.io/&quot;&gt;veed.io&lt;/a&gt; have increased in popularity and users expects ever more sophisticated video editing capabilities inside modern video based web apps.&lt;/p&gt;
&lt;h2 id=&quot;video-editing-use-cases&quot;&gt;Video Editing Use Cases&lt;/h2&gt;
&lt;p&gt;Let’s first outline use cases and requirements of video editing applications on the web. These will inform our discussion of technical features of respective solutions below and grant a conceptual framework for evaluating potential benefits and drawbacks of each solution.&lt;/p&gt;
&lt;h3 id=&quot;simple-video-editing&quot;&gt;Simple Video Editing&lt;/h3&gt;
&lt;p&gt;Let’s start with the base case, &lt;strong&gt;simple video edits&lt;/strong&gt; including trimming, cropping and resizing and simple effects such as adjusting brightness or saturation. This is usually sufficient feature set to support video editing for the following use cases:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sales Outreach Videos:&lt;/strong&gt; Sales teams often need to quickly edit customer-specific videos to personalize their outreach. This may involve trimming irrelevant portions, adding company logos, or adjusting brightness to ensure visual clarity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Messaging Applications:&lt;/strong&gt; These often require basic editing tools to allow users to crop, trim, or apply simple filters to shared videos, ensuring they’re concise and visually appealing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Screencasting:&lt;/strong&gt; Screencasting tools benefit from trimming and resizing capabilities to focus on key parts of recorded screens. Adding effects like brightness adjustment can make tutorials clearer and more professional.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CMS Systems:&lt;/strong&gt; Content management systems may offer built-in video editing to help users optimize media assets for specific platform requirements, such as resizing for web embeds or adding subtle branding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Screen Recording Applications:&lt;/strong&gt; Screen recording applications often include simple editing options for cleaning up recorded content by trimming extraneous sections or cropping to highlight the most relevant parts.&lt;/p&gt;
&lt;h3 id=&quot;video-annotation&quot;&gt;Video Annotation&lt;/h3&gt;
&lt;p&gt;Next, users might want to add an additional layer of information to videos and overlay other assets, such as stickers, shapes, overlays, or text. Crucially these assets need to be time-based—that is, users need control over when the asset is shown so that particular video sequences can be referenced. This introduces the need for a timeline to arrange different video components relative to each other in time, as well as features like voice-over and audio track support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;E-commerce Reviews:&lt;/strong&gt; Sellers and reviewers can annotate product demo videos with callouts, price tags, and feature highlights to make the content more engaging and informative.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Claims Management / Insurance:&lt;/strong&gt; Insurance companies can use annotation to highlight key details in submitted video claims, such as timestamps of damage or explanatory text overlaying critical sections of footage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real Estate:&lt;/strong&gt; Realtors might annotate property walkthroughs by adding labels, dimensions, or descriptive text overlays to highlight key features of the home or property.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Educational Applications:&lt;/strong&gt; Instructors can use annotation tools to emphasize key moments in lectures or tutorials, such as overlaying text with formulas or concepts, or adding visual shapes to guide attention.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Productivity Tools:&lt;/strong&gt; Users can annotate meeting recordings with timestamps, text notes, or overlay diagrams to summarize key decisions or action points.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Healthcare and Telemedicine:&lt;/strong&gt; Medical professionals might annotate diagnostic videos or procedure recordings to explain findings or highlight areas of interest for training purposes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Customer Support &amp;#x26; Onboarding Tools:&lt;/strong&gt; Companies can add annotations to video tutorials or troubleshooting guides to direct users through specific steps or highlight important information.&lt;/p&gt;
&lt;h3 id=&quot;video-composition&quot;&gt;Video Composition&lt;/h3&gt;
&lt;p&gt;As we’re moving away from single media editing to creating video compositions of several types of media such as audio tracks, text, images, animations, and effects to create appealing visual designs, a well-designed timeline becomes even more important. Users need to manage many different video components in time, requiring user-friendly ways to browse and integrate external assets. This editor variant is most relevant for the following use cases:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Tech (Promotional Videos):&lt;/strong&gt; Marketers can create visually stunning promotional videos by combining custom animations, background music, and text overlays for branding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Media (Stories and Reels):&lt;/strong&gt; Social media creators can quickly craft short, engaging videos that combine multiple assets like stickers, animations, and dynamic transitions tailored to platform-specific formats.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Event Highlight Reels:&lt;/strong&gt; Event organizers can compile videos, photos, and music into cohesive highlight reels that encapsulate the essence of the occasion.&lt;/p&gt;
&lt;h3 id=&quot;template-based-video-creation&quot;&gt;Template-based Video Creation&lt;/h3&gt;
&lt;p&gt;For many applications, users need starting points and examples for their designs. Starting from a blank canvas is rarely necessary for most use cases. Take a simple product video that includes promotional text, a brand logo, and animations. There is no need to reinvent the wheel for these types of videos. Instead, design applications should offer template libraries to accelerate user workflows.&lt;/p&gt;
&lt;p&gt;Once we introduce workflows involving several stakeholders—such as designers setting up a certain brand framework and marketers working with and adapting these preconfigured designs—templates need to be able to constrain what edit operations adaptors can perform. These requirements are particularly important for these use cases:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Digital Asset Management:&lt;/strong&gt; Organizations can manage and deploy branded video templates across teams, ensuring consistent design and messaging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Media Publishing:&lt;/strong&gt; Social media managers can utilize templates for quick turnaround on platform-specific video formats, such as Instagram Stories or LinkedIn posts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Tech:&lt;/strong&gt; Marketing teams can rely on pre-designed templates to churn out campaign videos at scale while maintaining brand consistency.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Training Videos:&lt;/strong&gt; HR or L&amp;#x26;D departments can adapt existing templates to quickly produce training materials customized for different teams or scenarios.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;IMG.LY&amp;#39;s Video Editor enables template based constraints&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1380px) 1380px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1380&quot; height=&quot;789&quot; src=&quot;https://img.ly/_astro/Video-Templating_1eQR66.webp&quot; srcset=&quot;/_astro/Video-Templating_7I73m.webp 640w, /_astro/Video-Templating_1h8MhA.webp 750w, /_astro/Video-Templating_1R3Qif.webp 828w, /_astro/Video-Templating_Z2oAeix.webp 1080w, /_astro/Video-Templating_ZYbYlz.webp 1280w, /_astro/Video-Templating_1eQR66.webp 1380w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;creative-automation-for-video&quot;&gt;Creative Automation for Video&lt;/h3&gt;
&lt;p&gt;Finally, you can leverage data and automation to generate variations of your templates at scale, significantly boosting the productivity of use cases where users need to either test a large number of designs, publish to different channels with different requirements, or adapt designs to many slightly different instances, for example, menu designs for a franchise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Tech:&lt;/strong&gt; Marketers can generate hundreds of ad variations for A/B testing or localization by dynamically adjusting text, visuals, or calls to action.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Media Publishing:&lt;/strong&gt; Social media teams can automate the creation of videos tailored to platform specifications, such as aspect ratios or resolution, while retaining core branding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;E-commerce:&lt;/strong&gt; Retailers can produce personalized product showcase videos for different customer segments, featuring tailored offers, pricing, or recommendations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hospitality Industry:&lt;/strong&gt; Hotels and restaurants can dynamically generate location-specific promotional videos showcasing seasonal offers, menus, or events.&lt;/p&gt;
&lt;h2 id=&quot;essential-video-editing-features&quot;&gt;Essential Video Editing Features&lt;/h2&gt;
&lt;p&gt;The above use cases are enabled by a set of features from simple transforms to complex compositions. Some video editors are focused more on manipulating individual video clips while others are more oriented towards video creation providing fully-fledged multi-media composition tool. This concise overview serves as a reference for evaluating video editing solutions:&lt;br&gt;
Transforms&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cut, Trim, and Split&lt;/strong&gt;: Basic editing tools for segmenting video clips.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resize and Scale&lt;/strong&gt;: Adjusts clip dimensions, ensuring proper fit or aspect ratio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crop and Rotate&lt;/strong&gt;: Controls framing and orientation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zooming Capabilities&lt;/strong&gt;: A UX feature enabling detailed editing and close-up views for precision.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;adjustments&quot;&gt;Adjustments&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Basic Adjustments&lt;/strong&gt;: Controls brightness, contrast, and other visual enhancements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filters and Effects&lt;/strong&gt;: Sets the visual appearance and atmosphere of videos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio Tracks and Mixing&lt;/strong&gt;: Supports multi-track audio adjustments and volume balancing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Text and Overlay Options&lt;/strong&gt;: Allows visual enhancements with text, captions, and emojis, providing opacity and layering options.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;composition&quot;&gt;Composition&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-media Composition&lt;/strong&gt;: Overlaying images, stickers, text as well as audio tracks are essential for creating videos through composition.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-Track Editing&lt;/strong&gt;: Elements and layers need to be position relative to each other in time allowing the creation of complex composition.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Canvas-Based Editing&lt;/strong&gt;: Provides a flexible workspace for positioning and layering media elements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeline Management&lt;/strong&gt;: Split, join and arrange clips on a timeline. Manages the positioning of clips and timing for seamless transitions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animations&lt;/strong&gt;: Make static elements dynamic and control their behavior in time. Can be use to create videos from scratch and enhance the storytelling workflow of existing ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;IMG.LY&amp;#39;s Video Editor Timeline Feature&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1376px) 1376px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1376&quot; height=&quot;960&quot; src=&quot;https://img.ly/_astro/Video-Editor-Timeline_Z1nLaxM.webp&quot; srcset=&quot;/_astro/Video-Editor-Timeline_Z2giwjW.webp 640w, /_astro/Video-Editor-Timeline_ZYWIGq.webp 750w, /_astro/Video-Editor-Timeline_1NmLoH.webp 828w, /_astro/Video-Editor-Timeline_Z23wuov.webp 1080w, /_astro/Video-Editor-Timeline_Z2pwGVX.webp 1280w, /_astro/Video-Editor-Timeline_Z1nLaxM.webp 1376w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-technology-landscape&quot;&gt;The Technology Landscape&lt;/h2&gt;
&lt;p&gt;Some time in the early 2000s the web started to be viewed as a platform to run applications not just a distributed database to deliver static html documents. While Javascript development was not yet at a point to serve as foundation for the kind of application development we see today, Adobe Flash filled the role of development platform. Video editing in the early days of the web was mainly provided by Flash-based tools involving simple transform operations such as trimming and basic transitions. Java applets were another way to deliver processing intensive programs via the browser while executing them outside of the browser inside the JVM. These early attempts were either too clunky, since they could not run natively in the browser or lacked the performance to be useful for high quality editing.&lt;/p&gt;
&lt;p&gt;When HTML5 came onto the scene in the early 2000s it became possible to handle multimedia content natively in the browser. Coupled with significant performance advances of Javascript and the introduction of WebRTC this opened the door for video editing on the web.&lt;/p&gt;
&lt;p&gt;Some early cloud-based editors, such as WeVideo and Magisto, while more convenient and user-friendly than its predecessors still suffered from performance issues due to latency and lacked the depth of features found in desktop software.&lt;/p&gt;
&lt;p&gt;In the past few years advances such as WebAssembly and Javascript libraries built upon it e.g. ffmpeg.js have revolutionised browser-based video editing. User can now perform complex editing tasks like multi-track timelines, video effects and real-time in-browser rendering. Modern web-based solution have even come to rival desktop apps, because they can take advantage of GPU acceleration, modern APIs like WebGL and UI frameworks such as React.&lt;/p&gt;
&lt;p&gt;Let’s have a look at the state of the art web technologies that allow us to create performant video editing experiences inside the browsers. We are going to explore their relative strength, their complexities and conclude with when to best use each of these technologies:&lt;/p&gt;
&lt;h3 id=&quot;canvas-api&quot;&gt;Canvas API&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API&quot;&gt;HTML5 Canvas API&lt;/a&gt; should be most familiar to most modern web developers, since it’s a familiar and popular way to render 2D graphics in the browser. It’s use for video editing is limited and restricted to simple overlays, trimming, composition and animation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Canvas is the least complex of the technologies introduced below and overlaps with the WebGL feature set to some extend, it’s API is well-known to most web developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; Canvas is lightweight, compatible across all browsers, and easy to implement, making it a great choice for simple use cases that require basic effects and no timeline.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; While well suited for simpler tasks Canvas lacks the GPU-acceleration of WebGL, hence it is not recommended for resource intensive operation or performance sensitive use cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Choose Canvas for simple editing tasks, like trimming or basic overlays, or if you need a fallback technology that works well on legacy browsers and devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;webgl&quot;&gt;WebGL&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API&quot;&gt;WebGL&lt;/a&gt; opens up the power of GPU-accelerated graphics to the browser, making it the default choice for any use case requiring high performance rendering. As such modern Javascript video editing solution are well served by webGL when looking to render visual effects in real time, add transitions or facilitate multi-layer compositions by leveraging the GPU.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; WebGL comes with a steep learning curve especially if you are unfamiliar with 3D graphics processing, shaders and GPU programming.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; WebGL delivers high performance for processing complex video effects and can handle significant volume of data without latency. That makes it ideal for advanced, highly responsive video editing features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; It can be challenging to engineer modular and maintainable WebGL code, debugging shaders and ensuring consistent performance across devices is an art in itself. WebGL might also be overpowered for simple editing use cases that do not justify the added complexity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Use WebGL if you’re creating a video editor with high-performance demands, particularly if real-time effects, transitions, or multi-layer compositing are needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;webcodecs-api&quot;&gt;WebCodecs API&lt;/h3&gt;
&lt;p&gt;Next up in our arsenal of formidable web technologies is a recent addition to modern browsers, WebCodecs, provide direct access to hardware accelerated video encoding and decoding.&lt;/p&gt;
&lt;p&gt;The WebCodecs API is a recent addition to the browser, allowing direct access to hardware-accelerated video decoding and encoding. This API makes it easier to handle high-resolution video without delays, thanks to efficient decoding directly in the browser.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; WebCodecs is relatively easy to use for those familiar with media formats. However, you may need other technologies for rendering and complex editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; This API offers quick access to hardware acceleration, ideal for managing large video files. With it, you can efficiently handle high-definition video playback and streaming.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; Browser support for WebCodecs is still expanding, so compatibility might be a concern. Additionally, WebCodecs alone doesn’t provide a full editing suite; it needs to be combined with rendering and compositing technologies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; WebCodecs is perfect if you need efficient decoding and encoding, especially for handling high-definition playback or live streaming.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;webassembly-wasm&quot;&gt;WebAssembly (Wasm)&lt;/h3&gt;
&lt;p&gt;The next performance frontier browser pushed towards was enabling near-native performance by compiling languages like C++ or Rust into a format that efficiently runs in Javascript. This format is &lt;a href=&quot;https://webassembly.org/&quot;&gt;WebAssembly&lt;/a&gt;, which makes it possible to handle computationally expensive tasks like encoding, decoding or frame manipulation inside the browser.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Working with WebAssembly is significantly more complex that the technologies discussed above. Developers need knoweldge of C++ or Rust as well as experience compiling to Wasm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; WebAssembly enables browsers to handle complex video processing tasks, such as encoding and decoding, with near-native performance. Libraries such as FFmpeg build upon WebAssembly to make familiar video tools available to web developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; Development with Wasm is complex, and debugging can be a challenge. Additionally, Wasm modules may increase load times.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Use WebAssembly when building native libraries for complex operation and expensive computations, such as encoding and decoding.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our article o&lt;a href=&quot;https://img.ly/blog/how-to-build-a-video-editor-with-wasm-in-react/&quot;&gt;n building a video editor with React and Wasm&lt;/a&gt; gives you a real-world starting point for your own apps.&lt;/p&gt;
&lt;h3 id=&quot;mediastream-api&quot;&gt;MediaStream API&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaStream&quot;&gt;MediaStream API&lt;/a&gt; is essential for gaining easy access to live video sources from within the browser, such as webcams. If your video editing app includes a feature for real-time recording or streaming the MediaStream API is an essential tool.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; MediaStream exposes a fairly simple API and is relatively easy to learn for experienced web developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; This API is well-suited for video feeds with low latency such as recording or streaming and does require addition encoding or decoding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; Any use case requiring post-production video has to rely on additional technologies or frameworks, as the MediaStream API is limited to live feeds. The quality of the stream depends on the input source and can vary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Use MediaStream for applications with live recording or streaming functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;web-audio-api&quot;&gt;Web Audio API&lt;/h3&gt;
&lt;p&gt;The final web technology essential for video editing is the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API&quot;&gt;Web Audio API&lt;/a&gt;. Whether you want to add effects or mix multiple audio tracks, this API offers sophisticated tools for audio manipulation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; For developers unfamiliar with audio processing the learning curve can be stepp, however the API is well designed and there is a host of educational resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; Web Audio API allows precise control over audio enabling your app to offer audio adjustments such as effects or reverb and multi-track editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt; It can be challenging to accurately synchronize audio with video, especially if your app includes a real-time component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Opt for Web Audio API when audio editing is a core feature of your video editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;using-these-technologies-together&quot;&gt;Using These Technologies Together&lt;/h3&gt;
&lt;p&gt;Together, these technologies can be use to build a comprehensive browser based editor that is virtually indistinguishable from its desktop based counterparts. Different parts of the video editing workflow can be handled by each technology, while some choices have to made depending on the complexity and requirements of your projects, e.g. whether you’ll need resource intensive processing or an integration will real-time sources.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Video Decoding&lt;/strong&gt; - WebCodecs API (for efficient video loading and playback).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering&lt;/strong&gt; - WebGL (for high-performance effects) and Canvas API (for simpler editing features).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complex Processing&lt;/strong&gt; - WebAssembly (for encoding/decoding and using native libraries like FFmpeg).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio Processing&lt;/strong&gt; - Web Audio API (for mixing and adding effects to soundtracks).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Live Recording&lt;/strong&gt; - MediaStream API (to capture live video from devices).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;open-source-javascript-video-editing-libraries&quot;&gt;Open Source Javascript Video Editing Libraries&lt;/h2&gt;
&lt;p&gt;Fortunately in many cases someone has already done the heavy lifting and abstracted those browser APIs into simple to use libraries and frameworks. We’ll explore the most prominent ones distinguishing between projects that are for processing raw video and those that already provide an API for you to use. It is important to note that the libraries introduced below do not provide a video editing UI, unfortunately there are no open source video editors offering an end user interface that meet the standards for inclusion in a production grade application. None of the projects we evaluated met the demands we place on third-party libraries with respect to robustness, stability, maintenance and future development. However many can provide good starting points and references on how to build your own UI such as &lt;a href=&quot;https://github.com/mifi/reactive-video&quot;&gt;Reactive Video&lt;/a&gt; for React UIs.&lt;/p&gt;
&lt;h3 id=&quot;ffmpegjs&quot;&gt;FFmpeg.js&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ffmpegwasm/ffmpeg.wasm&quot;&gt;FFmpeg.js&lt;/a&gt; is the JavaScript port of the popular FFmpeg library compiled into WebAssembly. It enables developers to manipulate and process raw video files entirely in the browser. You can trim, convert formats, extract audio, and apply filters to videos without needing external software. However, FFmpeg just gives you the raw toolchain for building video editing features, you are still tasked with building the entire UX and editing workflows. We have an extensive guide on FFmpeg that you can consult to explore its capabilities and get started learning FFmpeg syntax.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Most comprehensive library for web based video and audio processing.&lt;/li&gt;
&lt;li&gt;Fully client-side, no need for server-side processing.&lt;/li&gt;
&lt;li&gt;Highly flexible, allowing fine-grained control over video workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Fairly complex for beginners with a steep learning curve, requires familiarity with FFmpeg’s command-line syntax.&lt;/li&gt;
&lt;li&gt;FFmpeg is licensed under LGPL which makes it ill-suited for most commercial projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**When to Use:**FFmpeg.js is best suited for projects with custom requirements and UI making it necessary to exert fine-grained control over video processing tasks, especially for use cases like format conversion, advanced editing pipelines, or serverless video workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following two libraries allow you to programatically create and edit videos, we focus on the most stable, popular libraries here, while there might be promising up and comers we want to ensure a degree of dependability of the third-party code to be used in production systems.&lt;/p&gt;
&lt;h3 id=&quot;remotion&quot;&gt;Remotion&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.remotion.dev/&quot;&gt;Remotion&lt;/a&gt; is a React-based framework that enables developers to edit or create videos programmatically in a declarative fashion using React components. React’s declarative syntax makes it comparatively simple to manage video content and Remotion provides a convenient UI for previewing and editing videos. While its studio UI cannot be embedded directly, Remotion can serve as the graphics processing engine for custom UIs. Although it is a commercial project, it offers a generous free tier for individuals and small businesses.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Leverages React’s declarative model for seamless video creation.&lt;/li&gt;
&lt;li&gt;Provides robust video preview capabilities for iterative development.&lt;/li&gt;
&lt;li&gt;Flexible integration with custom-built UIs.&lt;/li&gt;
&lt;li&gt;Generous free tier for non-commercial and small-scale projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The built-in studio UI cannot be embedded, requiring developers to create their own UI for embedding.&lt;/li&gt;
&lt;li&gt;React-specific, limiting use in non-React environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;**When to Use:**Use Remotion when building React-based video applications that require programmatic video generation or dynamic video content. It’s ideal for teams already familiar with React and for applications where embedding is not a core requirement.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;etrojs&quot;&gt;&lt;strong&gt;Etro.js&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Similarly to Remotion, Etro.js is a JavaScript framework for programmatic video editing, it is framework agnostic and provides an API for simple composition of layers, effects and exporting videos.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Includes support for advanced effects using GLSL shaders.&lt;/li&gt;
&lt;li&gt;Designed for in-browser video workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downsides:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Minimal community support compared to larger projects.&lt;/li&gt;
&lt;li&gt;Requires additional effort to create a full UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Suitable for applications where programmatic control and customization are key.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;extensibility&quot;&gt;Extensibility&lt;/h2&gt;
&lt;p&gt;An important consideration when deciding to buy a prebuilt video editing solution is the degree of customization and extensibility required by your use case versus how critical speed to market is. While most SDKs provide enough flexibility by exposing cor API to build a solution that best suits your needs, this level of technical control comes at the expense of higher development and maintenance efforts. White-label solutions on the other end of the spectrum offer limited customization often relying on iFrames for embedding while providing maximum speed to market. If you are still in the phase where you need to make the business case for video editing features these might be key to allowing to quickly iterate. To learn more about weighing the pros and cons of SDK vs. White-label explore our &lt;a href=&quot;https://img.ly/blog/sdk-vs-white-label-consider-these-differences-when-you-choose-a-solution/&quot;&gt;extensive guide on the topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;IMG.LY’s CE.SDK achieves extensibility by providing an &lt;a href=&quot;https://img.ly/blog/img-ly-sdk-plugin-system/&quot;&gt;interface for plugins&lt;/a&gt; that allow developers to add custom features and UI elements.&lt;/p&gt;
&lt;h2 id=&quot;cross-platform-video-editing&quot;&gt;Cross Platform Video Editing&lt;/h2&gt;
&lt;p&gt;While this post is dedicated specifically to Javascript video editing an important consideration for choosing a video editing tech stack is whether there exists an intermediary output format that preserves editing operations so that videos can be edited on other devices and platforms. This is important for collaborative video editing use cases as well as use cases where videos are captured and basic edits performed on mobile and the finishing touches performed on the desktop.&lt;br&gt;
These consideration are particular pertinent for the Real Estate, Telemedicine and Productivity use cases described above, since they involve either a multi-device or collaborative component.&lt;/p&gt;
&lt;p&gt;At most common libraries or SDKs can achieve that by offering support for some form of serialization, that is exporting the edit operations along with the unedited video to then reapply edits upon import.&lt;/p&gt;
&lt;p&gt;IMG.LY’s CE.SDK, on the other hand, is the only video editing SDK that is truly cross-platform. That means it is built atop a single creative engine that is portable to any platform. Whether iOS, Android, Desktop, or the Web, every platform uses the same underlying tech and uses the same custom format for scenes which contain all assets and edits making error-prone serializations obsolete.&lt;/p&gt;
&lt;p&gt;Furthermore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iOS and Android make use of the same underlying API.&lt;/li&gt;
&lt;li&gt;Cross platform feature parity is baked into the cake. Since core functionality is implemented at the engine level, features are guaranteed to be available on both platform, although the timeline might differ somewhat.&lt;/li&gt;
&lt;li&gt;Designs are 100% interoperable and consistent between platforms. Exporting and importing design files across platforms works seamlessly and final renderings are guaranteed to be consistent.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;javascript-video-editing--generative-ai&quot;&gt;Javascript Video Editing &amp;#x26; Generative AI&lt;/h2&gt;
&lt;p&gt;Generative AI is impacting video editing and generation across the board. Video generation obvious application of generative AI, but AI is also changing the way we we compose, create an edit videos in more subtle ways.&lt;/p&gt;
&lt;p&gt;Features such as automated transitions, color grading, voice enhancement, voice over generation, background removal or inpainting are&lt;/p&gt;
&lt;p&gt;Currently, these capabilities are offered by multiple specialized providers, such as ElevenLabs and OpenAI’s Sora. Firstly, that means modern Javascript video editors need to be open enough to serve as integrators for various, programmatically combining voice tracks, video clips, text, audio and other media before presenting users with an editing UI. Secondly, traditional video editing needs to enable the human in the loop. AI is still imperfect and manually refining unchangeable artifacts through prompts is inefficient and tedious. Instead the output by AI must remain editable and any editor solution smoothly interface with those artifacts to allow users to add the necessary polish, swap out media and regenernate individual parts of the scene.&lt;/p&gt;
&lt;p&gt;To explore what this might look like in practice have a look at our CEO Eray Basar’s latest project building an AI video generator on top of &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CE.SDK&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When building or integrating a JavaScript video editor, developers and PMs have to navigate a complex technology landscape and make myriad decisions along the way. This guide has covered everything from essential use cases and feature sets to the cutting-edge technologies that underly browser-based video editing. Whether your project requires basic trimming tools or advanced multimedia composition, understanding the benefits and downsides of the various solutions like Canvas, WebGL, WebCodecs, WebAssembly, and more is crucial for choosing the right stack.&lt;/p&gt;
&lt;p&gt;We’ve also explored how open-source tools like FFmpeg.js, Remotion, and Etro.js can accelerate development, while SDKs like IMG.LY’s CE.SDK offer unmatched extensibility and cross-platform compatibility. For those navigating the impact of generative AI on video editing, the need for seamless integration and user-centric design remains important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you’re looking for a robust, modern video editing solution for your web application, explore our showcase and start a free trial.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Jan</dc:creator><media:content url="https://blog.img.ly/2024/12/Javascript-Editor--1-.jpg" medium="image"/><category>Video Editing</category><category>CE.SDK</category><category>Automation</category><category>Cross-Platform</category><category>JavaScript</category></item><item><title>IMG.LY Research: AI-based Generative Design Editing</title><link>https://img.ly/blog/img-ly-research-ai-based-generative-editing/</link><guid isPermaLink="true">https://img.ly/blog/img-ly-research-ai-based-generative-editing/</guid><description>Combine Large Language Models (LLMs) with CE.SDK for design edits and automated creative workflows.</description><pubDate>Tue, 16 Jul 2024 10:44:05 GMT</pubDate><content:encoded>&lt;p&gt;Generative AI is transforming the tech landscape, finding applications in virtually every field. At &lt;a href=&quot;https://img.ly/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=generative-editing&quot;&gt;IMG.LY&lt;/a&gt;, we’re exploring how these advancements can revolutionize creative workflows. This article presents a research project, where we integrate Large Language Models (LLMs) with our flagship product, CreativeEditor SDK (CE.SDK), to enable natural language-driven design edits.&lt;/p&gt;
&lt;p&gt;Our flagship product, CreativeEditor SDK (CE.SDK) allows for advanced creative workflows for countless use cases in industries ranging from &lt;a href=&quot;https://img.ly/industries/print&quot;&gt;print&lt;/a&gt; to &lt;a href=&quot;https://img.ly/industries/marketing-tech&quot;&gt;marketing tech&lt;/a&gt;. Most use cases can be realized with the out-of-the-box feature set, but it also exposes a best-in-class API, called Engine API, to build complex custom workflows with designs and videos.&lt;/p&gt;
&lt;p&gt;In this article, we will showcase how to combine our CE.SDK Engine API with LLMs to edit designs with natural language.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://storage.googleapis.com/imgly-static-assets/static/blog/videos/imgly-research/imgly-ai-template-editor-demo.mp4&quot; controls autoplay muted loop playsinline&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-llms&quot;&gt;Introduction to LLMs&lt;/h2&gt;
&lt;p&gt;Generative AI is often associated with chatbots, but its capabilities stretch further. It is a versatile text processor that can transform any textual input into various structured outputs. This adaptability is due to its training on diverse textual patterns, allowing it to support a wide range of text-to-text applications beyond just generating conversational prose.&lt;/p&gt;
&lt;p&gt;Carefully crafting an input text (prompt) in a way that instructs the LLM to output a specific structured output format allows us to use LLMs to solve almost any arbitrary text-based task.&lt;/p&gt;
&lt;p&gt;Crafting prompts is an art in itself. When ensuring that we receive the required output we need to adhere to the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consider what type of data our model was trained on to ensure the correct formatting of our input text. The most basic example is using English as our “main prompt language” since most LLMs are mainly trained on English text samples.&lt;/li&gt;
&lt;li&gt;All necessary problem-specific information to solve the task needs to be included in the prompt. While LLMs often possess an inherent understanding of the world inferred from the vast amount of text they are trained on, they may not know much about our specific problem. Furthermore, LLMs have the notorious tendency to hallucinate, that is fill in missing context with incoherent or incorrect information. To ensure the best performance, the input to the LLM must provide as much context as possible.&lt;/li&gt;
&lt;li&gt;Finally, we need to instruct the LLM well enough to output text-based data in a format we can then parse and process.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;human-vs-ai-workflows-for-executing-design-tasks&quot;&gt;Human vs. AI Workflows for Executing Design Tasks&lt;/h2&gt;
&lt;p&gt;We started this project with the vision to use generative AI to magically handle requests like these (in increasing order of complexity):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Make the logo bigger&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Translate this design into German&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Adopt this template to our brand colors and brand assets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Transform this Instagram story portrait design into a landscape YouTube thumbnail&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When trying to delegate a task to an AI, it’s best to start by thinking about how these tasks are currently solved by humans.&lt;/p&gt;
&lt;p&gt;Let’s walk through how a human would complete a task such as&lt;br&gt;
&lt;code&gt;Make the logo bigger&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Humans would visually scan the design and automatically segment it by its elements such as objects, backgrounds, or text.&lt;/li&gt;
&lt;li&gt;Humans would then read and comprehend the task “Make the logo bigger”&lt;/li&gt;
&lt;li&gt;Finally, users would use their existing knowledge of how to move and interact with design software to fulfill the task by manipulating the individual elements in the design.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on these considerations we can extract the implicit knowledge necessary to fulfill a task and make it explicit for the benefit of our LLM.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Design Representation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To enable the LLM to understand and manipulate a design, it is essential to provide a representation of the design. This can be either textual or a mix of textual and visual (if the LLM has vision capabilities) data. While supplying the current design as a raster image to the LLM is trivial, serializing a CE.SDK design into a textual format requires a custom serialization process. The textual representation is important since it allows the LLM to identify, address, and comprehend the different components of the design effectively.&lt;/p&gt;
&lt;p&gt;Refer to &lt;code&gt;Appendix: Use-Case dependent serialization of CE.SDK Designs&lt;/code&gt; for a more in-depth explanation of how to accomplish this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Editing Protocol:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;LLMs do not interact with design software using traditional human interfaces like a mouse, keyboard, or visual feedback. Therefore, we need a specific protocol for the LLM to propose changes to the design. We have developed a method where we pass a textual representation of the design to the LLM as part of the prompt so that the LLM can indicate changes to the design by returning a modification of this representation.&lt;/p&gt;
&lt;p&gt;Practically, this means that if we pass in an element such as &lt;code&gt;&amp;#x3C;Image id=&quot;1337&quot; x=”100” y=&quot;100&quot; .../&gt;&lt;/code&gt;, the LLM can change those x and y attributes by simply returning &lt;code&gt;&amp;#x3C;Image id=&quot;1337&quot; x=&quot;0&quot; y=&quot;0&quot; .. /&gt;&lt;/code&gt; inside its output text. Since we can identify the design element that was changed using the ID attribute, we can then calculate the programmatic changes that need to be applied to the design, like in this case &lt;code&gt;engine.block.setPositionX(1337, 0)&lt;/code&gt; and &lt;code&gt;engine.block.setPositionY(1337, 0)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Refer to &lt;code&gt;Appendix: Parsing and transforming LLM response&lt;/code&gt; for a deeper look into this topic.&lt;/p&gt;
&lt;h2 id=&quot;using-generative-ai-to-execute-design-related-tasks&quot;&gt;Using Generative AI to Execute Design-Related Tasks&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Employ LLMs to modify and improve CE.SDK design templates.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2000px) 2000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2000&quot; height=&quot;879&quot; src=&quot;https://img.ly/_astro/ai-generated-design-templates-LLM_1BWRFe.webp&quot; srcset=&quot;/_astro/ai-generated-design-templates-LLM_1etJt1.webp 640w, /_astro/ai-generated-design-templates-LLM_Z2amSOe.webp 750w, /_astro/ai-generated-design-templates-LLM_2jWNYV.webp 828w, /_astro/ai-generated-design-templates-LLM_Lp5Ga.webp 1080w, /_astro/ai-generated-design-templates-LLM_2qLpKx.webp 1280w, /_astro/ai-generated-design-templates-LLM_Z1OfXUH.webp 1668w, /_astro/ai-generated-design-templates-LLM_1BWRFe.webp 2000w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Based on what we have learned, we assemble a workflow, with the LLM as the center point that allows the LLM to execute design-related tasks on any of our CE.SDK designs. This workflow can be divided into two sub-tasks: Composing an input text (prompt) with all necessary context and parsing and applying the output of the LLM to the CE.SDK design.&lt;/p&gt;
&lt;h3 id=&quot;composing-the-input-text&quot;&gt;Composing the Input Text&lt;/h3&gt;
&lt;p&gt;As seen in the graphic above we first compose the input text based on different components to provide the model with all necessary context to fulfill the user’s editing request: This includes a general text to “instruct” the model, the actual request that the user entered, an exemplary design representation to explain our output format to the model and a representation of the currently edited design.&lt;/p&gt;
&lt;p&gt;The general, static text to “instruct” the model is composed of the following three parts.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What we are trying to achieve in general:&lt;br&gt;
&lt;code&gt;&quot;You are an AI with expertise in design, specifically focused on XML representations of designs&quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Output format instructions:&lt;br&gt;
&lt;em&gt;Your responses should only contain one XML document. Ensure that you do not introduce new attributes to any XML elements. You can change image elements by setting the alt attribute, which then will be used to search Unsplash for a fitting image. A sample alt text is “A mechanic changing tires with a pair of beautiful work gloves on”.&lt;br&gt;
Additionally, pay close attention to the layout: verify that no elements in the XML document extend beyond the page boundaries. This constraint is critical for maintaining consistency and accuracy in XML formatting. Always double-check your XML output for these requirements.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The actual user request:&lt;br&gt;
e.g., &lt;code&gt;&quot;Make the logo bigger&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By including a textual representation of a comprehensive example design we can show the model which layer types are available as well as which properties of those layers can be manipulated.&lt;/p&gt;
&lt;p&gt;The model now has all the necessary context and building blocks to respond to user requests in a format that we can process downstream.&lt;/p&gt;
&lt;h3 id=&quot;applying-the-output-text&quot;&gt;Applying the Output Text&lt;/h3&gt;
&lt;p&gt;In the first step, we scan the output text for an XML-like document and if we find one, attempt to parse it.&lt;/p&gt;
&lt;p&gt;This will yield a structured data object we can compare to the one we passed in and calculate which elements have been modified, added, or removed.&lt;/p&gt;
&lt;p&gt;The resulting change set can then be translated into specific calls to the &lt;a href=&quot;https://img.ly/docs/cesdk/js/user-interface/ui-extensions-d194d1/&quot;&gt;CE.SDK Engine API&lt;/a&gt; to change the current design.&lt;/p&gt;
&lt;h2 id=&quot;issues-faced&quot;&gt;Issues faced&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Latency&lt;/strong&gt;: One issue with state-of-the-art models is their big latency: Each LLM response contains approximately 1000 tokens. That means each request takes 7-45 seconds (depending on the model) to complete. This long delay may be unacceptable for some user experiences. However, we see this issue as transitory and expect upcoming models to have much smaller latency while maintaining their capabilities.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing&lt;/strong&gt;: Each request/response with GPT-4 turbo as a backing model costs around 5 cents and restricts some use cases. We also expect the pricing to drop significantly. The new GPT-4o model for example reduces the price by half.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hallucinations&lt;/strong&gt;: LLMs do not always follow the instructions properly and, e.g., produce output that is not parsable. Hallucinations directly correlate with the capabilities of the model and this issue is not apparent at current state-of-the-art LLMs like e.g GPT-4/GPT-4o.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We present a novel and adaptable approach to use Generative AI and LLMs specifically to interact with IMG.LY’s CreativeEditor SDK. We showcase how this technology can be used to execute common design requests on arbitrary CE.SDK Designs. The proposition that LLMs can understand textual representations of visual elements was by no means obvious. This research project has revealed that it is very well within the scope of LLMs to translate instructions from a visual semantic context to its textual representation and back. This invites more inquiries into LLMs as assistants for tasks with a heavy visual component such as design.&lt;/p&gt;
&lt;p&gt;While further research is needed to make this technology available in production environments, we are confident that Generative AI-based editing will play a big role in the future of Graphics and Video editing.&lt;/p&gt;
&lt;h2 id=&quot;appendix-use-case-dependent-serialization-of-cesdk-designs&quot;&gt;Appendix: Use-case Dependent Serialization of CE.SDK Designs&lt;/h2&gt;
&lt;p&gt;LLMs work based on “tokens” which are equal to words. However, a design, like e.g a poster design or a social media graphic, is highly visual. That means that we need a way to convert a design into text, a way to serialize it. Our CE.SDK engine can serialize an existing scene using our &lt;code&gt;engine.block.saveToString&lt;/code&gt; method. However, this serialization contains a huge pile of information that is not necessary to do edits inside the file. LLMs are priced by token and their speed is also relative to the number of tokens the input and output have. Thus, the number of tokens should be reduced.&lt;/p&gt;
&lt;p&gt;We looked at several ways to convert the current state of the design into a textual representation. Since GenAI is trained on a lot of (X)HTML which has an XML-like format, we decided to serialize any designs into a tag-based XML-like format.&lt;/p&gt;
&lt;p&gt;The IMG.LY editor internally refers to design elements like images or texts as “blocks”. These blocks are uniquely identifiable and addressable using a numeric ID. We use this ID to be able to identify a serialized design block in the input and output of the LLM. Example: &lt;code&gt;&amp;#x3C;Image id=&quot;12582927&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;800&quot; height=&quot;399&quot; /&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For each of the CE.SDK block types like e.g “Text” or “Graphics” (representing images or vector shapes), we will the CE.SDK Engine API to query very specific data from the block. That means that for example we only have a text attribute for Text blocks.&lt;/p&gt;
&lt;p&gt;This rather specific mapping of only certain properties from the CE.SDK design into the text serialization allows us to optimize the design serialization for different use cases. A use-case where we e.g. want to automatically name each layer does maybe not require fine-grained information about e.g the font size.&lt;/p&gt;
&lt;h2 id=&quot;appendix-parsing-and-transforming-llm-response&quot;&gt;Appendix: Parsing and transforming LLM response&lt;/h2&gt;
&lt;p&gt;The LLM answers with arbitrary tokens. It’s not possible to restrict the response to a certain syntax. By settling on a well-defined and widely used format we instruct the model to also reply with an XML-like document, similar to the one we passed in as “current state”.&lt;/p&gt;
&lt;p&gt;After receiving the LLM’s Response we first make sure that only a single XML document is present inside the response. We then compare the retrieved XML document with the state of the Design that we passed into the LLM and generate a change set. This change set contains entries like “Color of block with ID=123 has changed”. These change set entries are then converted into programmatic commands, like e.g &lt;code&gt;engine.block.setColor(123)&lt;/code&gt; and executed on the current design.&lt;/p&gt;
&lt;p&gt;One challenges when working with an LLM is the inability to restrict the output space. Thus, we are never guaranteed that the LLM did not add e.g new XML node names or that it even replies with a proper, valid XML-like document. The only lever to influence the probability of a proper XML-like document is to use strong prompting and LLM that are good at following those instructions.&lt;/p&gt;
&lt;p&gt;In our tests, state-of-the-art models like GPT-4 can follow those instructions without any further tooling.&lt;/p&gt;
&lt;h2 id=&quot;further-research-topics&quot;&gt;Further Research Topics&lt;/h2&gt;
&lt;p&gt;It’s also worth exploring fine-tuning an LLM specifically for this task which could improve the performance of the LLM for the specific tasks.&lt;/p&gt;
&lt;p&gt;It would also be possible to use more advanced libraries like &lt;a href=&quot;https://github.com/guidance-ai/guidance&quot;&gt;Guidance&lt;/a&gt;, which allows to define a grammar for the LLM response thus making sure that the output of the LLM is always parseable.&lt;/p&gt;
&lt;p&gt;Another way to improve the performance would be to methodically test different prompt templates and find a way to measure and compare the output quality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you for reading!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3,000+ creative professionals gain exclusive access and hear of our releases first—&lt;/strong&gt;&lt;a href=&quot;https://share.hsforms.com/1IgAOV1wASXGPnFG4ZPLejg1hk3i&quot;&gt;&lt;strong&gt;subscribe&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;to our newsletter and never miss out.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Mirko</dc:creator><media:content url="https://blog.img.ly/2024/07/0_AI-Template-generator.jpg" medium="image"/><category>AI</category><category>Automation</category><category>Design Editor</category><category>Machine Learning</category></item><item><title>How Printers Can Leverage Creative Automation</title><link>https://img.ly/blog/how-printers-can-leverage-creative-automation/</link><guid isPermaLink="true">https://img.ly/blog/how-printers-can-leverage-creative-automation/</guid><description>Discover how creative automation can revolutionize print production and transform the print industry.</description><pubDate>Tue, 04 Apr 2023 09:58:54 GMT</pubDate><content:encoded>&lt;p&gt;The emergence of print as a service and print-on-demand has changed the traditional way we think about printing, creating many possibilities for customized products, such as personalized photo books and bespoke t-shirts. However, to meet the ever-evolving needs of customers, printers must constantly innovate and streamline their operations. This is where &lt;strong&gt;creative automation&lt;/strong&gt; wins.&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://beta3.infotrends.com/news/editors-desk/2020/august/how-to-leverage-automation-for-print-production-in-hard-times/&quot;&gt;Keypoint Intelligence&lt;/a&gt;, only a mere 7% of Print Service Providers in North America had adopted a fully or mostly automated approach across their departments in 2020. This underscores the crucial role that creative automation can play in transforming the print industry. But what exactly does creative automation mean, and how can it revolutionize print production? Let’s find out!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1200px) 1200px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1200&quot; height=&quot;742&quot; src=&quot;https://img.ly/_astro/automation-statistics_1KcImB.webp&quot; srcset=&quot;/_astro/automation-statistics_Z2sVV8u.webp 640w, /_astro/automation-statistics_Z1x4snL.webp 750w, /_astro/automation-statistics_Z1rFMM3.webp 828w, /_astro/automation-statistics_365jk.webp 1080w, /_astro/automation-statistics_1KcImB.webp 1200w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-creative-automation&quot;&gt;What is Creative Automation?&lt;/h2&gt;
&lt;p&gt;To understand the power of creative automation, it’s critical to draw a line between the &lt;strong&gt;production of creative assets&lt;/strong&gt; and &lt;strong&gt;ad units&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Although many creative assets may eventually turn into ads, they first need to be integrated into a broader ad unit that incorporates other non-graphical elements like &lt;em&gt;headlines, text&lt;/em&gt;, and &lt;em&gt;landing pages&lt;/em&gt;. This ad unit is then assigned to a specific campaign.&lt;/p&gt;
&lt;p&gt;By leveraging creative automation, each stage of the creative asset production process can be automated, enabling the entire ad production process across all placements to be streamlined.&lt;/p&gt;
&lt;p&gt;To clarify, dynamic creative automates media buying, while creative automation utilizes advanced software to produce stunning designs quickly. This approach offers several benefits, including improved efficiency, reduced costs, and higher product quality.&lt;/p&gt;
&lt;h2 id=&quot;creative-automation-for-print-service-providers-and-print-on-demand&quot;&gt;Creative Automation for Print Service Providers and Print-on-Demand&lt;/h2&gt;
&lt;p&gt;The potential advantages of creative automation for &lt;strong&gt;Print Service Providers&lt;/strong&gt; are significant, particularly in terms of streamlining the design process.&lt;/p&gt;
&lt;p&gt;With tools like CE.SDK, printers can rapidly create bespoke designs for t-shirts, business cards, and other products, while also taking advantage of a wide range of templates, styles, and layouts that can be easily customized to suit any project. This not only saves time, but also ensures that each design is unique and of outstanding quality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Print-on-Demand companies&lt;/strong&gt;, on the other hand, can also leverage the power of creative automation to offer personalized products to customers in a rapid and efficient manner.&lt;/p&gt;
&lt;p&gt;By utilizing creative automation tools, print-on-demand companies can develop high-quality designs for photo books, t-shirts, and mugs, without the need for manual intervention in the design process.  This evolves into significant time savings, cost reductions, and increased profitability, allowing print-on-demand companies to stay ahead of the competition.&lt;/p&gt;
&lt;h2 id=&quot;how-to-apply-creative-automation-in-print&quot;&gt;How to Apply Creative Automation in Print&lt;/h2&gt;
&lt;p&gt;So, how can printers apply creative automation in print? There are several key elements to consider, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Variable Data Printing&lt;/strong&gt; is a printing technique that allows the personalization of each print piece, based on specific customer data. By automating this process, Print Service Providers can increase efficiency and accuracy, while reducing costs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Constraints&lt;/strong&gt; might seem like a limitation, but they’re actually a key factor in ensuring that designs are consistent during the creation process and meet industry standards. By automating the constraint process, printers can ensure that designs are consistent and meet expectations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templates&lt;/strong&gt; are pre-designed layouts that can be used for specific products, such as business cards or brochures. Automation of the template process allows the quickly creating of high-quality designs, without having to start from scratch each time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Styles&lt;/strong&gt; are a set of design elements, such as colors, fonts, and images, that can be used to create a consistent look and feel across all designs. The style automation process brings the possibility to create a cohesive brand image, increasing brand recognition and customer loyalty.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layouts&lt;/strong&gt; refer to the arrangement of design elements on a page, such as images, text, and graphics. Their automation provides fast creation of stunning designs, without having to manually arrange each element.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design Validation&lt;/strong&gt; is like having an eagle eye that spots mistakes (such as incorrect dimensions) before they become costly printing errors. Automating the design validation process allows printers to quickly identify and correct errors, reducing the risk of printing errors and increasing customer satisfaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;creative-automation-in-print-with-cesdk&quot;&gt;Creative Automation in Print with CE.SDK&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/products/creative-sdk/&quot;&gt;&lt;strong&gt;CE.SDK&lt;/strong&gt;&lt;/a&gt; is a powerful tool for creative automation in print, taking care of the entire design process, from layout to validation.&lt;/p&gt;
&lt;p&gt;With CE.SDK, you can easily create brilliant designs for various products, without having to spend time on manual design processes. The platform also offers a range of templates, styles, and layouts that can be easily customized to meet the needs of each project.&lt;/p&gt;
&lt;p&gt;For instance, let’s say you want to create a gorgeous photo book for a client. With CE.SDK, all you have to do is upload your images, select a template, and customize the design elements.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Let your users cherish their favorite memories by uploading their photos to a photo book template. Try this custom UI yourself in our showcases.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1395px) 1395px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1395&quot; height=&quot;865&quot; src=&quot;https://img.ly/_astro/image-0-min_Z28lC66.webp&quot; srcset=&quot;/_astro/image-0-min_rOyS8.webp 640w, /_astro/image-0-min_24VFzY.webp 750w, /_astro/image-0-min_Z26BOug.webp 828w, /_astro/image-0-min_Z1KICQ3.webp 1080w, /_astro/image-0-min_ZwC5Hb.webp 1280w, /_astro/image-0-min_Z28lC66.webp 1395w&quot;&gt;&lt;/p&gt;
&lt;p&gt;CE.SDK will take care of the rest, automatically arranging the images into a beautifully designed photo book that includes text, graphics, and other design elements. This not only saves time, but also ensures that each photo book is unique and of high quality.&lt;/p&gt;
&lt;p&gt;Here are some easy steps to follow when creating a &lt;a href=&quot;https://img.ly/demos/photobook-ui/web/&quot;&gt;photo book&lt;/a&gt;:&lt;/p&gt;
&lt;h4 id=&quot;step-1-organize-your-photos&quot;&gt;Step 1: Organize your Photos&lt;/h4&gt;
&lt;p&gt;Choose the photos you want to include in your photo book and organize them in a way that tells a story. For instance, you can arrange them chronologically or by theme.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Storytelling is everything – allow users to organize their photos to pick and choose from.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1351px) 1351px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1351&quot; height=&quot;810&quot; src=&quot;https://img.ly/_astro/photo-book-SDK-template-for-web_1t67rX.webp&quot; srcset=&quot;/_astro/photo-book-SDK-template-for-web_MdgNn.webp 640w, /_astro/photo-book-SDK-template-for-web_Z2dbxzd.webp 750w, /_astro/photo-book-SDK-template-for-web_Z1Rj0aW.webp 828w, /_astro/photo-book-SDK-template-for-web_Z1eahNS.webp 1080w, /_astro/photo-book-SDK-template-for-web_Z1FNhkJ.webp 1280w, /_astro/photo-book-SDK-template-for-web_1t67rX.webp 1351w&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;step-2-customize-your-photo-book&quot;&gt;Step 2: Customize your Photo Book&lt;/h4&gt;
&lt;p&gt;Then, add a personal touch to your photo book by customizing the text, adding captions, or changing the font style and color.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Users might expect custom text options to give their memories a final touch.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1007px) 1007px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1007&quot; height=&quot;109&quot; src=&quot;https://img.ly/_astro/photo-book-SDK-template-for-web_2_NADSD.webp&quot; srcset=&quot;/_astro/photo-book-SDK-template-for-web_2_ZpDR6j.webp 640w, /_astro/photo-book-SDK-template-for-web_2_ZXVJkj.webp 750w, /_astro/photo-book-SDK-template-for-web_2_K4mom.webp 828w, /_astro/photo-book-SDK-template-for-web_2_NADSD.webp 1007w&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;step-3&quot;&gt;Step 3&lt;/h4&gt;
&lt;p&gt;Once you’ve finished customizing your template, you can preview the final result, and send it out for printing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A memory ready for print!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1066px) 1066px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1066&quot; height=&quot;755&quot; src=&quot;https://img.ly/_astro/photo-book-SDK-template-for-web_3_ZnPlWR.webp&quot; srcset=&quot;/_astro/photo-book-SDK-template-for-web_3_Z15cjv0.webp 640w, /_astro/photo-book-SDK-template-for-web_3_Z155fNY.webp 750w, /_astro/photo-book-SDK-template-for-web_3_Z132YqD.webp 828w, /_astro/photo-book-SDK-template-for-web_3_ZnPlWR.webp 1066w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In today’s ever-changing printing industry, printers need to be efficient, innovative, and creative to remain competitive. Creative automation provides an excellent solution, enabling printers to streamline their design process, reduce costs, and improve profitability while delivering exceptional, personalized products to their customers.&lt;/p&gt;
&lt;p&gt;CE.SDK is a powerful tool for creative automation in print, offering a wide range of customizable templates, styles, and layouts that can be tailored to meet the unique requirements of each project. With CE.SDK, printers can create stunning designs for a range of products, from personalized t-shirts to exquisite photo books, all while saving time and money.  &lt;a href=&quot;https://img.ly/docs/cesdk/&quot;&gt;Try CE.SDK for free&lt;/a&gt; and see the benefits of creative automation for yourself.&lt;/p&gt;</content:encoded><dc:creator>Natalia</dc:creator><media:content url="https://blog.img.ly/2023/04/design_automation_SDK-min.jpg" medium="image"/><category>How-To</category><category>Automation</category><category>Print</category><category>Creative Editor</category><category>Learning</category></item><item><title>Variable Data Printing: What Is It &amp; Why Do You Need It</title><link>https://img.ly/blog/variable-data-printing-definition-and-benefits/</link><guid isPermaLink="true">https://img.ly/blog/variable-data-printing-definition-and-benefits/</guid><description>Discover the power of VDP for automating processes, scaling personalization &amp; enhancing intimacy in marketing, advertising &amp; customer management.</description><pubDate>Fri, 03 Mar 2023 09:45:33 GMT</pubDate><content:encoded>&lt;p&gt;Variable data printing (VDP) has been around since the 1980s, helping businesses automate manual processes, scale personalization efforts, and utilize the power of direct mail marketing. While the term “variable data printing” may not be familiar to everyone, we encounter its use regularly in our day-to-day lives through bills, event tickets, or membership cards.&lt;/p&gt;
&lt;p&gt;VDP’s ability to leverage data and create personalized tangible items, such as postcards or brochures, provides a more intimate experience compared to digital communication. Although process automation is a significant advantage of VDP, there are many other ways to use it.&lt;/p&gt;
&lt;p&gt;In this article, we’ll explore the most common applications of VDP and the best practices for working with it.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h2&gt;
&lt;p&gt;To fully understand the advantages of variable data printing (VDP), let’s start with a clear definition. VDP, also referred to as variable data imaging, is a digital printing technique that enables the creation of numerous customized materials in a single print run. This process is powered by software that can generate data-driven designs or templates by pulling variables from databases or files.&lt;/p&gt;
&lt;p&gt;The variables used in VDP can automatically generate unique and personalized materials based on data sources. Anything that can be customized, such as names, addresses, messages, or images, can be utilized as a variable. These elements can be changed on each printed piece without slowing down the printing process.&lt;/p&gt;
&lt;p&gt;To illustrate how VDP works in practice, let’s consider a scenario where a company offers a loyalty program for customers to collect points when they make purchases. To encourage more spending, customers can use their accumulated points to receive discounts or freebies. Although points and bonuses can be accessed through an app or website, the company can create immediate gamification by sending a personalized card with every new purchase.&lt;/p&gt;
&lt;p&gt;To personalize that card, we are looking at three separate variables: name, number of points, and type of discount that can be applied. To manually generate all variations of the same template would be counterproductive, but with variables connected to a database it’s an automated process. A name is connected to a number of points, which in turn are connected to discounts. The software does all the heavy lifting, while marketers and designers can focus on other tasks.&lt;/p&gt;
&lt;h2 id=&quot;common-applications-of-vdp&quot;&gt;Common Applications of VDP&lt;/h2&gt;
&lt;p&gt;Although VDP was originally used to automate manual mail processes, its usefulness extends beyond that. Its ability to personalize marketing and advertising materials quickly and efficiently has made it widely appreciated and used in various industries.&lt;/p&gt;
&lt;p&gt;While there are many ways to use VDP, we’ll focus on its most common applications in marketing, advertising, and customer relationship management. These areas benefit greatly from the ability to tailor messages to specific audiences and create unique, personalized experiences.&lt;/p&gt;
&lt;h3 id=&quot;marketing&quot;&gt;Marketing&lt;/h3&gt;
&lt;p&gt;From quickly generating business cards to creating custom QR codes, variable data printing is a big part of marketing efforts for most businesses. Apart from handling internal processes, VPD also has a hand in scaling personalized marketing campaigns. The growing preference for personalized messaging and products goes alongside increased usage of VDP.&lt;/p&gt;
&lt;p&gt;Production of personalized labels, packaging, or brochures is one of the best ways to leverage VDP in marketing. It can be used as a step in a broader personalization campaign, like generating custom QR codes to bring users to personalized landing pages. Or be a venture on its own, like &lt;a href=&quot;https://us.coca-cola.com/store/personalized-bottle&quot;&gt;“Share a Coke”&lt;/a&gt; by Coca-Cola and its widely successful personalization of labels.&lt;/p&gt;
&lt;h3 id=&quot;advertising&quot;&gt;Advertising&lt;/h3&gt;
&lt;p&gt;Variable data printing brought new life to direct mail, moving away from what once was perceived as junk and irrelevant advertising, and bringing about a new age of valuable and relatable mail. A &lt;a href=&quot;https://www.fundera.com/resources/direct-mail-statistics&quot;&gt;recent study&lt;/a&gt; reported that 70% of consumers see direct mail as more personal than online interactions, with 54% claiming they want direct mail from brands that interest them. Moreover, direct mail has the highest response rate among all advertising channels being five to nine times higher than other forms, with a simple act of adding a name to a direct mail piece that can increase response rates by 135%.&lt;/p&gt;
&lt;p&gt;Taking advantage of VPD in advertising usually includes customized leaflets or coupons with images and content based on age or demographics. One of the personalization examples is including custom maps with steps on how to reach an advertised location, making it much more relatable and easy to act on.&lt;/p&gt;
&lt;h3 id=&quot;customer-relationship-management&quot;&gt;Customer Relationship Management&lt;/h3&gt;
&lt;p&gt;While VDP helps marketing and advertising drive acquisition, it’s also a great way to help with customer retention. Small and yet important gestures of appreciation like custom-made thank you and birthday cards can go a long way. As mentioned before, VDP can also be used to generate membership cards or personalized bonuses and discounts based on shopping preferences. Tapping into the power of variables, every printed material sent to a customer can be created in a way that will feel personal and appreciative, in turn helping sustain loyal customers.&lt;/p&gt;
&lt;h2 id=&quot;why-use-vdp&quot;&gt;Why Use VDP&lt;/h2&gt;
&lt;p&gt;Variable data printing is not reserved for a single industry or business type. It can be leveraged across multiple customer touchpoints, from the awareness stage via direct mail advertising, to a personalized label and thank you card shipped with a purchased product. VDP can also be used internally to show gratitude and appreciation to employees with custom-made cards and packaging. In fact, variable data printing can be used on any piece of printed content or design that can be personalized.&lt;/p&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;
&lt;p&gt;The advantages of variable data printing go hand-in-hand with the advantages of personalization. &lt;a href=&quot;https://www.twilio.com/blog/announcing-the-state-of-personalization-2021&quot;&gt;Studies show&lt;/a&gt; that customers respond much better to marketing materials they can connect to, with 60% of consumers saying they will likely become repeat buyers after a personalized shopping experience with a retailer.&lt;/p&gt;
&lt;p&gt;VDP can help create a valuable experience from start to finish and facilitate a meaningful connection between a brand and a customer. Some of the most prominent benefits are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Providing personalized shopping experience in the form of custom labels, packaging &amp;#x26; cards&lt;/li&gt;
&lt;li&gt;Building strong customer relationships with personalized thank you &amp;#x26; birthday cards, custom messaging, and discounts&lt;/li&gt;
&lt;li&gt;Delivering meaningful direct mail advertising with higher conversion rates&lt;/li&gt;
&lt;li&gt;Generating personalized marketing campaigns &amp;#x26; materials that customers can connect with&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bringing variable data printing to your workflows, whether it concerts marketing, advertising, HR, or sales, is a great way to tap into &lt;a href=&quot;https://img.ly/blog/why-companies-need-to-go-personal/&quot;&gt;powerful benefits of personalization&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;challenges&quot;&gt;Challenges&lt;/h3&gt;
&lt;p&gt;The main challenge of VDP is having software that can efficiently work with variables and generate print-ready designs, while also providing advanced design editing features.&lt;/p&gt;
&lt;p&gt;Since the popularization of personalization, variables can be leveraged in many different types of marketing materials. However, the design of those materials is equally important, and so it’s an automated print validation process.&lt;/p&gt;
&lt;p&gt;This challenge applies to companies that use variable data to generate designs, as well as Print Service Providers (PSP) working with VDP. For the PSP, another challenge is file format submission, especially if they don’t have a web-to-print editor their customers can use to submit their orders. Flawed print validation, incompatible format, low resolution, or insufficient quality could be costly mistakes to make. Hence, the best option for print service providers is to develop their own web-to-print editor with variable data printing that will take care of those problems and limit manual work to a minimum.&lt;/p&gt;
&lt;h2 id=&quot;example-of-leveraging-variable-data-printing-with-cesdk&quot;&gt;Example of Leveraging Variable Data Printing with CE.SDK&lt;/h2&gt;
&lt;p&gt;IMG.LY has developed CreativeEditor SDK to help integrate &lt;a href=&quot;https://img.ly/use-cases/variable-data-printing&quot;&gt;VDP&lt;/a&gt; into all designs in an easy and intuitive way. &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CE.SDK&lt;/a&gt; is fully customizable and can be integrated into a customer-facing web-to-print editor, providing powerful editing features, or an in-house design editor for all creative needs. Here’s an example of how you can leverage variables with our editor.&lt;/p&gt;
&lt;h3 id=&quot;creating-custom-thank-you-card&quot;&gt;Creating Custom Thank-You Card&lt;/h3&gt;
&lt;p&gt;As mentioned before, thank you cards are a great way to show appreciation and build stronger connections with both customers and employees. Creation of a custom thank-you card is pretty straightforward, here are the necessary steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Creating a Smart Template&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To create a personalized card, we begin by designing a template with variable fields. The front design remains consistent, while the back features unique personalized messages.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Design a template by adding images, text, or fun shapes and stickers.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1120px) 1120px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1120&quot; height=&quot;598&quot; src=&quot;https://img.ly/_astro/01_create_template-1_f1nPB.webp&quot; srcset=&quot;/_astro/01_create_template-1_DshRl.webp 640w, /_astro/01_create_template-1_Z23vRzl.webp 750w, /_astro/01_create_template-1_Z22g4xm.webp 828w, /_astro/01_create_template-1_Z1k7Jmg.webp 1080w, /_astro/01_create_template-1_f1nPB.webp 1120w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Assigning Placeholders&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next step is to choose the elements that will be personalized. For example, we may select a personalized greeting, such as “Hello {{name}}”, and address information. To insert a variable, we use double curly brackets {{}} and a placeholder name, such as {{firstname}} or {{address}}.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Take advantage of variables that serve as placeholders for information, such as customer names.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1120px) 1120px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1120&quot; height=&quot;527&quot; src=&quot;https://img.ly/_astro/02_assigning_placeholders_1MctnI.webp&quot; srcset=&quot;/_astro/02_assigning_placeholders_Z1dqOUT.webp 640w, /_astro/02_assigning_placeholders_i4vNS.webp 750w, /_astro/02_assigning_placeholders_Z1g3EsX.webp 828w, /_astro/02_assigning_placeholders_ZQmM65.webp 1080w, /_astro/02_assigning_placeholders_1MctnI.webp 1120w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Connecting Template to a Data Source&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The last step is connecting your template to a data source with list of variables. This can be done by using the &lt;a href=&quot;https://img.ly/docs/cesdk/js/create-templates/add-dynamic-content/text-variables-7ecb50/&quot;&gt;Creative Engine variable API&lt;/a&gt; to programmatically set values for the variables and render the final personalized card.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Design Validation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the example above, there shouldn’t be any issue with text exceeding beyond bleed line or other common print errors, however, design validation is an important feature of CE.SDK. It will automatically detect any issues that might cause a print error, cause trademark infringement or generate harmful content.&lt;/p&gt;
&lt;p&gt;And that’s it! We have created a template for custom thank-you card in three easy steps. Here is what a card would look like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A personalized hello: Create a custom card yourself with CE.SDK.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 621px) 621px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;621&quot; height=&quot;896&quot; src=&quot;https://img.ly/_astro/03_design_validation_Z2gOUY2.webp&quot; srcset=&quot;/_astro/03_design_validation_Z2gOUY2.webp 621w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Try creating a custom card with CE.SDK yourself on our &lt;a href=&quot;https://img.ly/demos/post-greeting-cards/web/&quot;&gt;showcase&lt;/a&gt; page!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/use-cases/variable-data-printing&quot;&gt;Variable data printing&lt;/a&gt; can be a valuable tool to boost performance and take initiatives to the next level. It can help scale personalization efforts, acquire new customers, add value to the final product, and make employees feel appreciated. By using VDP, businesses can efficiently grow and reap numerous benefits, with only a few obstacles that can be easily overcome with the right solution.&lt;/p&gt;
&lt;p&gt;To take advantage of the benefits of VDP and overcome its challenges, consider using &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CreativeEditor SDK&lt;/a&gt; and see how it can help you scale personalization and bring variable data printing to your company and customers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! To stay in the loop, subscribe to our&lt;/strong&gt; &lt;a href=&quot;https://photoeditorsdk.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;&lt;strong&gt;Newsletter&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Klaudia</dc:creator><media:content url="https://blog.img.ly/2023/03/VDP-print-product-web2print-web-application.jpg" medium="image"/><category>How-To</category><category>VDP</category><category>Automation</category><category>Creative Editor</category><category>Personlization</category><category>Web-to-print</category><category>Design Editor</category><category>Design Systems</category><category>Learning</category></item><item><title>Personalize or Perish: Why Companies Need to Go Personal</title><link>https://img.ly/blog/why-companies-need-to-go-personal/</link><guid isPermaLink="true">https://img.ly/blog/why-companies-need-to-go-personal/</guid><description>Learn about leveraging Personalization for deeper customer connections, increased brand loyalty and customer retention, and higher conversion rates. </description><pubDate>Tue, 21 Feb 2023 11:34:58 GMT</pubDate><content:encoded>&lt;p&gt;In the past, tailor-made marketing campaigns and personalized products were seen as a luxury that only a few companies could afford. However, as we enter 2023, personalization has become essential for all industries. Consumers now expect to see relevant and relatable content on a regular basis, which means that leveraging personalization on at least one channel has become a must-have.&lt;/p&gt;
&lt;p&gt;Many marketers already use personalization techniques to retain customers and boost conversions. However, with new trends constantly emerging, there’s a risk of falling behind. If you’re still unconvinced that personalization is the future, we’ve put together an overview of why it should be a top priority for your business strategy.&lt;/p&gt;
&lt;h3 id=&quot;what-is-personalization&quot;&gt;What is Personalization?&lt;/h3&gt;
&lt;p&gt;First, let’s clarify what personalization actually means. The most straightforward way to explain personalization would be tailoring of marketing materials, campaigns, and products to individuals’ specific characteristics, preferences, and needs in order to provide a more relevant and engaging experience.&lt;/p&gt;
&lt;p&gt;With technological development, companies are finding new ways to apply personalization across their businesses, ways beyond mere “Hello [name]” emails. For industries like e-commerce or printers, the personalization approach has been extended all the way to the production stage - allowing customers to incorporate their own designs and purchase a unique product made exclusively for them. Others, rely on algorithms to make sure that customers are always presented with the most relevant and engaging content. Regardless of the industry, everyone is looking to take advantage of personalization approaches.&lt;/p&gt;
&lt;h3 id=&quot;benefits-of-personalization&quot;&gt;Benefits of Personalization&lt;/h3&gt;
&lt;p&gt;Personalization is by default a user-centric approach, prioritizing relevance, usability, and impact of provided content and features. Thoroughly planned personalized marketing campaigns can make or break new product launches, boost subscription numbers, or convert lingering customers.&lt;br&gt;
For industries like e-commerce and print, enabling customers to design or customize their own product means higher sales and lower return rates - which translates to not only a higher profit margin but also a more sustainable shopping experience.&lt;/p&gt;
&lt;p&gt;Companies efficiently utilizing personalization efforts can expect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deeper connection between brand and customer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increased brand loyalty and customer retention&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Higher conversion rates&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Treating customers with individual attention and care creates a sense of connection going beyond just purchasing needs. When customers are faced with meaningful content they are able to find what they need more easily, creating a pleasant user experience. &lt;a href=&quot;https://instapage.com/blog/personalization-statistics&quot;&gt;Instapage&lt;/a&gt; reported that 74% of customers feel frustrated when website content is not personalized. Making them more likely to stick with brands that go the extra mile.&lt;/p&gt;
&lt;p&gt;Moreover, presenting customers with relevant recommendations or tailor-made discounts significantly increases chances of conversion. According to Business Insider, 47% of customers turn to Amazon if the brand they are shopping with doesn’t provide personalized product suggestions. The ability to quickly find what is needed might just be the difference between making a sale and losing a customer.&lt;/p&gt;
&lt;h2 id=&quot;leveraging-personalization&quot;&gt;Leveraging Personalization&lt;/h2&gt;
&lt;p&gt;Applications of personalization are limited only by imagination and creativity. The right personalization approach can sometimes equal to the success of an entire business. Hard to imagine Spotify being so popular without its flawless personalization algorithms alongside giants like Netflix or Amazon which heavily rely on personalization to retain subscriptions and push sales.&lt;/p&gt;
&lt;p&gt;Fortunately, personalization is not reserved for large enterprises only, it can be used just as efficiently by any other company, regardless of its size. Thanks to its versatility, it can be utilized across different channels, platforms, and consumer touchpoints. Some of the most popular uses of personalization include:&lt;/p&gt;
&lt;h3 id=&quot;marketing&quot;&gt;Marketing&lt;/h3&gt;
&lt;p&gt;For brands and marketing agencies, personalization usually translates to displaying personalized content - be it product, service, or piece of information, alongside ensuring relevant outreach - with tailor-made emails and ads. The success of marketing personalization efforts usually depends on quality of gathered data and right algorithms. Unfortunately, finding a winning approach means little without having a way to scale it. Companies that wish to succeed with their marketing personalization strategy usually have to turn to automation of workflows and creative materials.&lt;/p&gt;
&lt;h3 id=&quot;e-commerce&quot;&gt;E-Commerce&lt;/h3&gt;
&lt;p&gt;Apart from applying personalization in their marketing efforts, e-commerce companies have the advantage of extending it all the way to their products. Allowing customers to add a custom engraving or artwork creates a more intimate shopping experience with irreplaceable product added value. Companies that cannot offer those services have also found a way to leverage personalization, usually by providing options to add a custom greeting card, thank you note, or even record a custom message.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;This kind of personalization is becoming increasingly popular among beauty product consumers, as it adds a special touch and makes the product feel more unique and customized. Companies are benefiting from this trend by strengthening their relationship with customers, who feel more connected to the brand when they receive personalized products.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 388px) 388px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;388&quot; height=&quot;566&quot; src=&quot;https://img.ly/_astro/personalize-print-1_1tPVfG.webp&quot; srcset=&quot;/_astro/personalize-print-1_1tPVfG.webp 388w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;print-products&quot;&gt;Print Products&lt;/h3&gt;
&lt;p&gt;Print products might have the most exciting and yet still underutilized personalization growth possibility. While photo printers have been profiting from personalization for quite some time, there is still a large portion of the industry lagging behind. Personalization of any printed materials like photos, posters, cards, marketing materials, or apparel items is the future. And certainly, the future customers are impatiently looking forward to.&lt;/p&gt;
&lt;p&gt;However, personalization leaves nobody behind. For those unable to provide such services, there is a whole world of personalized packaging and labels to take advantage of and create a meaningful customer experience.&lt;/p&gt;
&lt;h2 id=&quot;personalization-challenges&quot;&gt;Personalization Challenges&lt;/h2&gt;
&lt;p&gt;With all the benefits and possibilities of personalization, it seems like every company should have mastered it by now. So why it isn’t so? Scaling personalization can proven to be a challenging task. It requires a strategy on how to gather data sensibly, translate it into initiatives, and bring those initiatives to life. Some of the most common challenges of scaling personalization are as follows.&lt;/p&gt;
&lt;h3 id=&quot;data-collection-and-preparation&quot;&gt;Data Collection and Preparation&lt;/h3&gt;
&lt;p&gt;In order to create relevant personalization of marketing content and materials first there must be data that can support this. With topics of privacy policies and data protection on the rise, targeted ads and campaigns might seem obsolete. The key to leveraging personalization is understanding the fine line between providing experience that feels relevant and welcomed, not invasive and overbearing. Another factor contributing to positive results is the transparency of collected data and how it’s being used. &lt;a href=&quot;https://hbr.org/2018/01/ads-that-dont-overstep&quot;&gt;Harvard Business Review&lt;/a&gt; conducted a study that reported that when customers were openly informed their ads were based on their online activity revenue grew by 38%. With data becoming a currency of its own, honest communication seems to be the key to successful personalization campaigns.&lt;/p&gt;
&lt;h3 id=&quot;creative-materials-production&quot;&gt;Creative Materials Production&lt;/h3&gt;
&lt;p&gt;Personalization is loved by marketers because they know how much it helps with engagement and conversion rates. However, it can be dreaded by designers and creative teams. Production of personalized marketing materials can create a painful bottleneck and freeze resources for extended periods of time. The only way to scale production and reduce efforts is by implementing software that can automate a large portion of the work with templates and variable data imports. Designers can create adjustable templates and the marketing team can adapt them to their needs, making the process fast and accessible to all.&lt;/p&gt;
&lt;h3 id=&quot;custom-prints&quot;&gt;Custom Prints&lt;/h3&gt;
&lt;p&gt;The most significant challenges of personalized print products usually revolve around artwork supply and print quality. Different resolutions, file formats, and design quality might mean the back and forth of proofreading, rejecting, and proofreading again. Custom prints might also pose a risk of misprints and trademark infringements, as well as mismatched expectations - especially if there is no preview function of the ready product. A solution for those headaches would be a web-to-print editor, which can not only improve the design creation process, but also automatically validate designs and generate previews.&lt;/p&gt;
&lt;h2 id=&quot;scale-personalization-with-cesdk&quot;&gt;Scale Personalization with CE.SDK&lt;/h2&gt;
&lt;p&gt;CreativeEditor SDK was developed with the thought of bringing automation and scalability to creative materials. Because of its versatility and extensive features, it can be applied across all industries and utilized on all channels and platforms, and addresses some of the most burning questions limiting the current use of personalization.&lt;/p&gt;
&lt;h3 id=&quot;personalized-cross-channel-content&quot;&gt;Personalized Cross-Channel Content&lt;/h3&gt;
&lt;p&gt;How do you create personalized content that can be implemented for a large audience across multiple channels, all with limited resources? The short answer is &lt;strong&gt;automation&lt;/strong&gt;. Creating countless variations of marketing materials has to be automated, otherwise, it cannot be scaled.&lt;/p&gt;
&lt;p&gt;The most efficient way is to work with adjustable templates and data variation imports. Designers can create as many templates as needed, making sure they stay on brand, while marketers and social media creators can adapt them to their needs.&lt;/p&gt;
&lt;p&gt;CreativeEditor SDK offers the possibility of creating smart templates with adjustable placeholders and constraints. This way, editing of any design is done in a controlled and predefined way. The editor can be used by internal teams, as well as external clients and customers, making the production of all marketing materials easily scalable.&lt;/p&gt;
&lt;h3 id=&quot;how-to-develop-a-web2print-editor-in-a-timely-manner&quot;&gt;How to Develop a Web2print Editor in a Timely Manner?&lt;/h3&gt;
&lt;p&gt;The most time-efficient way is to use Software Development Kit. SDKs contain powerful features with quick and easy integration and give the opportunity to stay on brand with customizable UI.&lt;/p&gt;
&lt;p&gt;Choosing CE.SDK, whether for photo prints, apparel, or marketing materials, can streamline the web2print process and solve many of the custom print challenges. With smart templates, companies can jumpstart their customers’ creative process, ensuring right design dimensions and quality. While automatic design validation safeguards the printing process with notifications of artwork exceeding bleed margin, as well as checking for harmful content or trademark infringements.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Regardless if you use it as a key component or part of a bigger strategy, personalization is here to stay, and it will most likely determine the success of many brands and industries. Staying up to date with current personalization trends is becoming a must for marketers, with a growing need to think outside the box. The ability to scale personalized marketing materials, and provide bespoke user experience and relevant recommendations, are the future of reaching conversion goals and building lasting relationships with customers.&lt;/p&gt;
&lt;p&gt;Companies will have to find ways to easily and efficiently scale personalization and bring it to their users. IMG.LY developed tools to help with those efforts. Learn more about &lt;a href=&quot;https://img.ly/products/creative-sdk&quot;&gt;CE.SDK&lt;/a&gt; capabilities or see how to use it for &lt;a href=&quot;https://img.ly/use-cases/creative-automation&quot;&gt;Creative Automation&lt;/a&gt; process or &lt;a href=&quot;https://img.ly/industries/print&quot;&gt;Web-to-Print&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to learn more about integrating CE.SDK, check out our &lt;a href=&quot;https://img.ly/docs/cesdk/js/what-is-cesdk-2e7acd/&quot;&gt;documentation&lt;/a&gt; or &lt;a href=&quot;https://img.ly/forms/free-trial&quot;&gt;try it for free&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading. To stay in the loop, subscribe to our&lt;/strong&gt; &lt;a href=&quot;https://photoeditorsdk.us13.list-manage.com/subscribe?u=dc9f652839dbb620d14d6d28d&amp;#x26;id=04a306e4b2&quot;&gt;&lt;strong&gt;Newsletter&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Klaudia</dc:creator><media:content url="https://blog.img.ly/2023/02/how-to-personalize-products-.jpg" medium="image"/><category>Automation</category><category>Personlization</category><category>Design Editor</category><category>Print</category><category>Learning</category></item><item><title>Content Moderation for User-Generated Designs with CE.SDK and Sightengine</title><link>https://img.ly/blog/content-moderation-for-user-generated-designs-with-ce-sdk-and-sightengine/</link><guid isPermaLink="true">https://img.ly/blog/content-moderation-for-user-generated-designs-with-ce-sdk-and-sightengine/</guid><description>Protect your users and your brand reputation without manual content moderation.</description><pubDate>Mon, 13 Jun 2022 14:07:54 GMT</pubDate><content:encoded>&lt;p&gt;Creating content and sharing it with others has become one of the core features offered by online services. As users publish their content to your website, you want to consider implementing a system to prevent inappropriate posts. Ideally, content will be programmatically moderated before it is uploaded on your platform. That is what you will learn in this article!&lt;/p&gt;
&lt;p&gt;Follow this step-by-step tutorial and learn how to integrate content moderation with Sightengine in your design process built with CreativeEditor SDK in React. At the end of this tutorial, you will achieve the &lt;a href=&quot;https://codesandbox.io/s/content-moderation-for-user-generated-designs-with-ce-sdk-and-sightengine-forked-8kc7te&quot;&gt;following result&lt;/a&gt;:&lt;/p&gt;
&lt;h2 id=&quot;why-you-should-moderate-user-generated-content&quot;&gt;Why You Should Moderate User-Generated Content&lt;/h2&gt;
&lt;p&gt;User-generated content represents a large portion of online content, whether text or multimedia. Empowering users with tools and features to create high-quality content is excellent. However, it is a common concern that potentially inappropriate content on your website will be associated with your brand. Naturally, you will want to avoid this.&lt;/p&gt;
&lt;p&gt;A recent example from the web-to-print industry serves as a cautionary tale: the German e-commerce company Spreadshirt neglected to moderate content on its t-shirt printing platform, leading to a wave of &lt;a href=&quot;https://www.beyond-print.net/market-spreadshirt-removes-tasteless-star-of-david-motif/&quot;&gt;outrage on social media&lt;/a&gt;. Even though the company reacted swiftly and stated an apology, Spreadshirt could have avoided most of the damage if it had implemented a system that automatically flags potentially harmful content. Of course, a religious or cultural symbol is not inherently inappropriate, but the misuse is.&lt;/p&gt;
&lt;p&gt;It is highly advisable to take precautions to prevent your company from facing similar adversity. A common problem, however, is the costly and time-consuming manual moderation, epecially when controlling multimedia files like images.&lt;/p&gt;
&lt;p&gt;Luckily, you can use CE.SDK and Sightengine to programmatically integrate moderation into your content design process without manual reviews.&lt;/p&gt;
&lt;h2 id=&quot;what-is-cesdk&quot;&gt;What is CE.SDK?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/products/creative-sdk?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;CreativeEditor SDK (CE.SDK)&lt;/a&gt; is a powerful, easy-to-use, and fully customizable design editor. With just a few lines of code, CE.SDK provides your application with template-based workflows and automation.&lt;/p&gt;
&lt;p&gt;The role-specific editing UI focuses on keeping content adaptation dead simple: in &lt;strong&gt;Creator Mode&lt;/strong&gt;, you have the liberty to create a design from scratch or customize existing templates. When creators are ready to share a design for others to use and customize in &lt;strong&gt;Adopter Mode&lt;/strong&gt; (Default UI), creators may decide which elements can be changed. See CE.SDK &lt;a href=&quot;https://img.ly/showcases/cesdk/web/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;in action&lt;/a&gt; or &lt;a href=&quot;https://img.ly/free-trial/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;try it for free&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-sightengine&quot;&gt;What is Sightengine?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://sightengine.com/&quot;&gt;Sightengine&lt;/a&gt; is a convenient tool for automatic content moderation. It detects and filters unwanted content in photos, videos, and live streams through fast, accurate, easy-to-integrate, privacy-compliant APIs.&lt;/p&gt;
&lt;p&gt;Sightengine offers you APIs to get moderation results instantly and effectively. The API-centric approach allows you to scale to up to tens of millions of images per month. You can have a look at the Sightengine &lt;a href=&quot;https://sightengine.com/demo&quot;&gt;demo&lt;/a&gt; or &lt;a href=&quot;https://dashboard.sightengine.com/signup&quot;&gt;try it for free&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;integrate-content-moderation-into-cesdk&quot;&gt;Integrate Content Moderation into CE.SDK&lt;/h2&gt;
&lt;p&gt;Let us look at how to implement an image editor with content moderation for your users. For this, you will learn how to use CE.SDK and React to implement an image design component and use the CE.SDK APIs to programmatically moderate the content with Sightengine on a Node.js server. You can try out a &lt;a href=&quot;https://img.ly/showcases/cesdk/web/content-moderation/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;live showcase&lt;/a&gt; of content moderation with CE.SDK.&lt;/p&gt;
&lt;p&gt;With the following steps, you can easily achieve this result with CE.SDK, React, Sightengine, and Node.js.&lt;/p&gt;
&lt;h3 id=&quot;1-get-started-with-cesdk&quot;&gt;1. Get Started with CE.SDK&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://img.ly/docs/cesdk/react/get-started/overview-e18f40/&quot;&gt;Integrate CreativeEditor SDK with React&lt;/a&gt; by using the official documentation. As you will see in the final snippet, this takes only a few lines of code.&lt;/p&gt;
&lt;p&gt;Now that you have a working CE.SDK instance, your users may unleash their creativity by designing templates and sharing them with others. The powerful APIs ensure control at every step of the editing process and allow programmatically performing operations, such as content moderation.&lt;/p&gt;
&lt;h2 id=&quot;2-build-a-content-moderation-api-with-sightengine&quot;&gt;2. Build a Content Moderation API with Sightengine&lt;/h2&gt;
&lt;p&gt;Let’s move on to content moderation with Sightengine. Keep in mind that any backend technology will work, but here you will implement a content moderation API based on Sightengine in Node.js.&lt;/p&gt;
&lt;h3 id=&quot;21-getting-started-with-sightengine&quot;&gt;2.1 Getting Started with Sightengine&lt;/h3&gt;
&lt;p&gt;First, you need a Sightengine account. If you do not have one yet, you can &lt;a href=&quot;https://dashboard.sightengine.com/signup&quot;&gt;create a free account&lt;/a&gt;. Fill out the form, click &lt;em&gt;Sign Up&lt;/em&gt;, and receive a verification email in your inbox. Click on the verification link and activate your account.&lt;/p&gt;
&lt;p&gt;Then, navigate to &lt;em&gt;API Keys&lt;/em&gt; on your Sightengine Dashboard page and retrieve your API &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;secret&lt;/code&gt; credentials. You will need them to interact with the Sightengine moderation APIs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;API-Keys&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1920px) 1920px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1920&quot; height=&quot;939&quot; src=&quot;https://img.ly/_astro/API-Keys_2qJUen.webp&quot; srcset=&quot;/_astro/API-Keys_ZlqYIr.webp 640w, /_astro/API-Keys_Z1w4Wxh.webp 750w, /_astro/API-Keys_133wET.webp 828w, /_astro/API-Keys_Z1wDt5P.webp 1080w, /_astro/API-Keys_Z19TsmB.webp 1280w, /_astro/API-Keys_1IfMS7.webp 1668w, /_astro/API-Keys_2qJUen.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;22-prerequisites&quot;&gt;2.2 Prerequisites&lt;/h3&gt;
&lt;p&gt;Here is a list of all prerequisites for the backend application you are going to build:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/get-npm&quot;&gt;Node.js and npm 8.x and higher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/express&quot;&gt;&lt;code&gt;express&lt;/code&gt;&lt;/a&gt; &gt;= 4.x&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/node-fetch&quot;&gt;&lt;code&gt;node-fetch&lt;/code&gt;&lt;/a&gt; &gt;= 3.x&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can add &lt;code&gt;express&lt;/code&gt; and &lt;code&gt;node-fetch&lt;/code&gt; to your project’s dependencies with the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install --save express node-fetch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;23-setting-up-a-nodejs-express-server&quot;&gt;2.3 Setting up a Node.js Express Server&lt;/h3&gt;
&lt;p&gt;Follow &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment&quot;&gt;this&lt;/a&gt; step-by-step guide to set up a Node.js Express development server. You will need this to perform an API call to Sightengine to moderate your content server-side. Any Sightengine API call involves your Sightengine &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;secret&lt;/code&gt; pair of credentials, and you do not want to expose them.&lt;/p&gt;
&lt;p&gt;You may also want to store the result of the moderation API in your database, as well as other data. For example, you might be interested in keeping track of how many times a particular user has violated the moderation rules to warn or ban them.&lt;/p&gt;
&lt;h3 id=&quot;24-implementing-a-content-moderation-api-in-your-nodejs-server&quot;&gt;2.4 Implementing a Content Moderation API in your Node.js Server&lt;/h3&gt;
&lt;p&gt;You can now implement a content moderation API in your Node.js Express server as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const fetch = require(&quot;node-fetch&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    router.get(&apos;/content-moderation&apos;, function (req, res) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if (!req.query.url) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            res.status(404).send(&quot;Please provide an image url&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // defining the Sightengine API parameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const params = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            url: req.query.url,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            models: &quot;nudity,wad,offensive&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            api_user: &quot;YOUR_SIGHTENGINE_USER&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            api_secret: &quot;YOUR_SIGHTENGINE_SECRET&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // generating the Sightengine API URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const queryString = new URLSearchParams(params).toString();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const requestOptions = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            method: &quot;GET&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const sightengineUrl = &quot;https://api.sightengine.com/1.0/check.json?&quot; + queryString&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // calling the Sightengine moderation API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const externalRes = await fetch(SightengineUrl, requestOptions)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // retrieving the moderation result from the Sightengine API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        const moderationResultText = await externalRes.text()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.append(&quot;Access-Control-Allow-Origin&quot;, [&quot;*&quot;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.append(&quot;Access-Control-Allow-Methods&quot;, &quot;GET&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.append(&quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        // returning the Sightengine moderation result text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        res.status(200).send(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take care of replacing &lt;code&gt;YOUR_SIGHTENGINE_USER&lt;/code&gt; and &lt;code&gt;YOUR_SIGHTENGINE_SECRET&lt;/code&gt; with your Sightengine pair of credentials retrieved before.&lt;/p&gt;
&lt;p&gt;Now, launch your Node.js server and reach the following URL below to use Sightengine to moderate the images specified in the URL query parameter:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    http://localhost:3000/content-moderation?url=&amp;#x3C;your_image_url&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;3-moderate-images-made-with-cesdk&quot;&gt;3. Moderate Images Made with CE.SDK&lt;/h2&gt;
&lt;p&gt;We will now use CE.SDK and Sightengine to programmatically moderate user-generated images. Before we can dive in, check the following requirements.&lt;/p&gt;
&lt;h3 id=&quot;31-prerequisites&quot;&gt;3.1 Prerequisites&lt;/h3&gt;
&lt;p&gt;This is the list of all the prerequisites you need to build for the frontend demo application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/get-npm&quot;&gt;Node.js and npm 8.x and higher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt; &gt;= 17&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/@cesdk/cesdk-js&quot;&gt;&lt;code&gt;@cesdk/cesdk-js&lt;/code&gt;&lt;/a&gt; &gt;= 1.5.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can add the &lt;code&gt;@cesdk/cesdk-js&lt;/code&gt; library to your project’s dependencies with the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install --save @cesdk/cesdk-js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, the demo application will use other libraries, although they are not strictly required to achieve the goals of this tutorial and can be omitted here.&lt;/p&gt;
&lt;h3 id=&quot;32-getting-started&quot;&gt;3.2 Getting Started&lt;/h3&gt;
&lt;p&gt;You can try out the demo application by cloning the &lt;a href=&quot;https://github.com/Tonel/content-moderation-with-cesdk-and-sightengine&quot;&gt;GitHub repository that supports this article&lt;/a&gt; with the following commands:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;git clone https://github.com/Tonel/content-moderation-with-cesdk-and-sightengine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd content-moderation-with-cesdk-and-sightengine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm i&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Otherwise, keep following this tutorial and build the demo application for content moderation by yourself.&lt;/p&gt;
&lt;p&gt;First, initialize a React project called &lt;code&gt;content-moderation-with-cesdk-and-sightengine&lt;/code&gt; by employing the &lt;a href=&quot;https://create-react-app.dev/docs/getting-started/&quot;&gt;Create React App&lt;/a&gt; command below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    npx content-moderation-with-cesdk-and-sightengine&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the &lt;code&gt;content-moderation-with-cesdk-and-sightengine&lt;/code&gt; folder should have the following file structure:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;content-moderation-with-cesdk-and-sightengine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── node_modules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── package.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── .gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── favicon.ico&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── index.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── logo192.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── logo512.png&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── manifest.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── robots.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── App.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── App.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── App.test.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── index.css&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── logo.svg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   ├── reportWebVitals.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   └── setupTests.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enter the &lt;code&gt;content-moderation-with-cesdk-and-sightengine&lt;/code&gt; folder and start a local server with these two commands:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;cd content-moderation-with-cesdk-and-sightengine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm start&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Visit &lt;a href=&quot;http://localhost:3000/&quot;&gt;http://localhost:3000/&lt;/a&gt; in your browser, and you should now be seeing the default Create React App screen below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;React-Screen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 983px) 983px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;983&quot; height=&quot;728&quot; src=&quot;https://img.ly/_astro/React-Screen_ZpeFfw.webp&quot; srcset=&quot;/_astro/React-Screen_2jrC6f.webp 640w, /_astro/React-Screen_Z7rdRp.webp 750w, /_astro/React-Screen_Z1UwlqM.webp 828w, /_astro/React-Screen_ZpeFfw.webp 983w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;33-integrate-the-moderation-check-into-your-design-process&quot;&gt;3.3 Integrate the Moderation Check into your Design Process&lt;/h3&gt;
&lt;p&gt;Notice that the demo application you are about to implement is just a simplified version of the app you can find in &lt;a href=&quot;https://github.com/imgly/cesdk-web-examples/blob/showcases/showcase-content-moderation/&quot;&gt;this GitHub repository&lt;/a&gt;. This demo app integrates the Sightengine moderation functionality with the CE.SDK design capabilities.&lt;/p&gt;
&lt;p&gt;Now, let’s move on to the main component where the integration takes place:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; CreativeEditorSDK &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;@cesdk/cesdk-js&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; ValidationBox &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;../ui/ValidationBox/ValidationBox&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; React, { useCallback, useEffect, useRef, useState } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;react&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { ReactComponent &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; RefreshIcon } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./refresh.svg&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { moderateImages } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./moderationUtils&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; styles &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;./ImageModerator.module.css&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; classNames &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;classnames&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; selectBlock&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;cesdk&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;blockId&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // deselecting all blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  cesdk.engine.block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;findAllSelected&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; cesdk.engine.block.&lt;/span&gt;&lt;span&gt;setSelected&lt;/span&gt;&lt;span&gt;(block, &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // selecting the block having the blockId passed as parameter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  cesdk.engine.block.&lt;/span&gt;&lt;span&gt;setSelected&lt;/span&gt;&lt;span&gt;(blockId, &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; ImageModerator&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; cesdkContainerDiv&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; useRef&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; cesdkRef&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; useRef&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;validationResults&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;setValidationResults&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; useState&lt;/span&gt;&lt;span&gt;([]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  useEffect&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // initializing CE.SDK if it has not been initialized yet&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (cesdkContainerDiv.current &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;cesdkRef.current) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        role: &lt;/span&gt;&lt;span&gt;&apos;Adopter&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        theme: &lt;/span&gt;&lt;span&gt;&apos;light&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        initialSceneURL: &lt;/span&gt;&lt;span&gt;`${&lt;/span&gt;&lt;span&gt;window&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;protocol&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; &apos;//&apos;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; window&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;}/cases/content-moderation/example.scene`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ui: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          elements: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            panels: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              settings: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            navigation: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              action: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                save: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        callbacks: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // calling this function when the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // user presses the &quot;Save&quot; button&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          onSave&lt;/span&gt;&lt;span&gt;: () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; runImageModerationCheck&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      CreativeEditorSDK.&lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;(cesdkContainerDiv.current, config).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        (&lt;/span&gt;&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          cesdkRef.current &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; instance;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          // running the moderation check on initialization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          runImageModerationCheck&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      if&lt;/span&gt;&lt;span&gt; (cesdkRef.current) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        cesdkRef.current.&lt;/span&gt;&lt;span&gt;dispose&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, [cesdkContainerDiv]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; runImageModerationCheck&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; useCallback&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;cesdkRef.current) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // retrieving the moderation results&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; validationResults&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; moderateImages&lt;/span&gt;&lt;span&gt;(cesdkRef.current);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    setValidationResults&lt;/span&gt;&lt;span&gt;(validationResults);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }, []);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;classNames&lt;/span&gt;&lt;span&gt;(styles.wrapper, &lt;/span&gt;&lt;span&gt;&apos;space-y-2&apos;&lt;/span&gt;&lt;span&gt;)}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{styles.header}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{styles.headerDiv}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;h4&quot;&lt;/span&gt;&lt;span&gt; style&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{{ color: &lt;/span&gt;&lt;span&gt;&apos;white&apos;&lt;/span&gt;&lt;span&gt; }}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              Content Moderation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;/&lt;/span&gt;&lt;span&gt;h3&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{styles.headerDivMessage}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              Check images for compliance with your content guidelines before&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              further processing and provide user feedback.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;/&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            onClick&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; runImageModerationCheck&lt;/span&gt;&lt;span&gt;()}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&apos;button button--white space-x-2&apos;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;Validate Image Content&amp;#x3C;/&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            &amp;#x3C;&lt;/span&gt;&lt;span&gt;RefreshIcon&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          &amp;#x3C;/&lt;/span&gt;&lt;span&gt;button&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;ValidationBox&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          results&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{validationResults}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          onSelect&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{(&lt;/span&gt;&lt;span&gt;blockId&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            selectBlock&lt;/span&gt;&lt;span&gt;(cesdkRef.current, blockId);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{styles.cesdkWrapper}&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &amp;#x3C;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{cesdkContainerDiv} &lt;/span&gt;&lt;span&gt;className&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;{styles.cesdk}&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &amp;#x3C;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; ImageModerator;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the first &lt;a href=&quot;https://reactjs.org/docs/hooks-effect.html&quot;&gt;&lt;code&gt;useEffect()&lt;/code&gt;&lt;/a&gt; hook, CE.SDK is initialized, and a callback on the save action is registered. This will take care of calling the &lt;code&gt;runImageModerationCheck()&lt;/code&gt; function when the user presses the CE.SDK &lt;em&gt;Save&lt;/em&gt; button. For more information on how callbacks work in CE.SDK, see &lt;a href=&quot;https://img.ly/docs/cesdk/react/concepts/events-353f97/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;the official documentation on observing events&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;runImageModerationCheck()&lt;/code&gt; retrieves the moderation results obtained from Sightengine and then stores it in the &lt;code&gt;validationResults&lt;/code&gt; array variable. This is then passed to the &lt;code&gt;ValidationBox&lt;/code&gt; component, which will show the results of the validation process to the end-user. None of this would be possible without the &lt;code&gt;moderateImages()&lt;/code&gt; function from the &lt;code&gt;moderationUtils.js&lt;/code&gt; file below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; moderateImages&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;cesdk&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // retrieving all image blocks with a name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; imageBlocksData&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; cesdk.engine.block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;findByType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;image&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;blockId&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      blockId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      url: cesdk.engine.block.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(blockId, &lt;/span&gt;&lt;span&gt;&apos;image/imageFileURI&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      blockType: cesdk.engine.block.&lt;/span&gt;&lt;span&gt;getType&lt;/span&gt;&lt;span&gt;(blockId),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      blockName: cesdk.engine.block.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;(blockId),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      return&lt;/span&gt;&lt;span&gt; block.blockName &lt;/span&gt;&lt;span&gt;!==&lt;/span&gt;&lt;span&gt; &apos;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Moderation check launched...&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // turning the moderation results on each image block into&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // a flat array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; imagesWithValidity&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; Promise&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    imageBlocksData.&lt;/span&gt;&lt;span&gt;flatMap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;imageBlockData&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      // retrieving the moderation results&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      const&lt;/span&gt;&lt;span&gt; imageModerationResults&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; callSightengineModerationAPI&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        imageBlockData.url&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(imageBlockData.blockName, imageModerationResults);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      return&lt;/span&gt;&lt;span&gt; imageModerationResults.&lt;/span&gt;&lt;span&gt;flatMap&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;checkResult&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ...&lt;/span&gt;&lt;span&gt;checkResult,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ...&lt;/span&gt;&lt;span&gt;imageBlockData,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      }));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Moderation check completed&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  return&lt;/span&gt;&lt;span&gt; imagesWithValidity.&lt;/span&gt;&lt;span&gt;flat&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// a cache variable to avoid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// calling the Sightengine API when not necessary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; complianceCache&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; callSightengineModerationAPI&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; async&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // if the url is already present in the cache, then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // return the result previously retrieved&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; (complianceCache[url]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; complianceCache[url];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // calling the Sightengine moderation API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; response&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // your endpoint URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &apos;https://europe-west3-img-ly.cloudfunctions.net/sightengineApiProxy?url=&apos;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      encodeURIComponent&lt;/span&gt;&lt;span&gt;(url),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      method: &lt;/span&gt;&lt;span&gt;&apos;get&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      headers: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        accept: &lt;/span&gt;&lt;span&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &apos;Accept-Language&apos;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;en-US,en;q=0.8&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &apos;Content-Type&apos;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;multipart/form-data;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; results&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; (results.error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(results.error);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; checkResults&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        name: &lt;/span&gt;&lt;span&gt;&apos;Weapons&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        description: &lt;/span&gt;&lt;span&gt;&apos;Handguns, rifles, machine guns, threatening knives...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        state: &lt;/span&gt;&lt;span&gt;percentageToState&lt;/span&gt;&lt;span&gt;(results.weapon),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        name: &lt;/span&gt;&lt;span&gt;&apos;Alcohol&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        description: &lt;/span&gt;&lt;span&gt;&apos;Wine, beer, cocktails, champagne...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        state: &lt;/span&gt;&lt;span&gt;percentageToState&lt;/span&gt;&lt;span&gt;(results.alcohol),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        name: &lt;/span&gt;&lt;span&gt;&apos;Drugs&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        description: &lt;/span&gt;&lt;span&gt;&apos;Cannabis, syringes, glass pipes, bongs, pills...&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        state: &lt;/span&gt;&lt;span&gt;percentageToState&lt;/span&gt;&lt;span&gt;(results.drugs),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        name: &lt;/span&gt;&lt;span&gt;&apos;Nudity&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        description: &lt;/span&gt;&lt;span&gt;&apos;Images that contain either raw nudity or partial nudity.&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        state: &lt;/span&gt;&lt;span&gt;percentageToState&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt; results.nudity.safe),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // storing the Sightengine results in the cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    complianceCache[url] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; checkResults;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; checkResults;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; percentageToState&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;percentage&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // defining the custom moderation logic based on the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // percentage returned by Sightengine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; (percentage &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; 0.8&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &apos;failed&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; (percentage &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; 0.4&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &apos;warning&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &apos;success&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we use the CE.SDK reference variable to retrieve all images in the scene through the CE.SDK APIs. Then, these are converted into URLs and passed &lt;code&gt;callSightengineModerationAPI()&lt;/code&gt; function, which takes care of calling the Sightengine moderation API, retrieving the results, using them to produce a new output, and returning it to the caller.&lt;/p&gt;
&lt;p&gt;We used an IMG.LY endpoint here to evade putting together a backend application. In a real-world scenario, replace &lt;code&gt;https://europe-west3-img-ly.cloudfunctions.net/sightengineApiProxy?url=&lt;/code&gt; with the URL of the &lt;code&gt;/content-moderation&lt;/code&gt; endpoint of your backend application. Also, note that a cache system was set up to avoid calling the Sightengine API too many times and using up call credits.&lt;/p&gt;
&lt;p&gt;This is what the demo application will look like after being launched and the moderation check has been executed:&lt;br&gt;
&lt;img alt=&quot;live-action-moderation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1918px) 1918px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1918&quot; height=&quot;928&quot; src=&quot;https://img.ly/_astro/live-action-moderation_g22UQ.webp&quot; srcset=&quot;/_astro/live-action-moderation_xu23A.webp 640w, /_astro/live-action-moderation_2lOxOG.webp 750w, /_astro/live-action-moderation_Pdqj8.webp 828w, /_astro/live-action-moderation_Z1AnpCm.webp 1080w, /_astro/live-action-moderation_1LCvNP.webp 1280w, /_astro/live-action-moderation_ZQcY5P.webp 1668w, /_astro/live-action-moderation_g22UQ.webp 1918w&quot;&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the Sightengine API correctly detects &lt;em&gt;drugs&lt;/em&gt; and &lt;em&gt;weapons&lt;/em&gt;. Next, remove the rightmost image containing a gun and click &lt;em&gt;Save&lt;/em&gt; to re-run the moderation check.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;detection&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1920px) 1920px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1920&quot; height=&quot;931&quot; src=&quot;https://img.ly/_astro/detection_ZflnCz.webp&quot; srcset=&quot;/_astro/detection_ZBLsO1.webp 640w, /_astro/detection_1CcGPE.webp 750w, /_astro/detection_1ADxoj.webp 828w, /_astro/detection_Z2sj5RQ.webp 1080w, /_astro/detection_Z256mPV.webp 1280w, /_astro/detection_1QiKB5.webp 1668w, /_astro/detection_ZflnCz.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sightengine no longer detects weapons in the image, proving that the moderation process is working as expected.&lt;/p&gt;
&lt;p&gt;Et voilà! You have learned to implement content moderation for user-generated images with CE.SDK and Sightengine.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;A challenge of user-generated content is avoiding the risk of hosting and displaying offensive or outright illegal content. Inappropriate content affects your user community and brand reputation and may even cause legal action against you.&lt;/p&gt;
&lt;p&gt;In this article, we used CE.SDK to initialize a fully-featured design editor in React. We employed its API to programmatically call a Node.js server using Sightengine to perform content moderation on images. This allows moderation of user-generated content automatically and prevents the upload of inappropriate content to your website.&lt;/p&gt;
&lt;p&gt;We are only scratching the surface of what is possible with CE.SDK – you can implement any UI on top of its powerful image processing API and extend the core functionality with features such as &lt;a href=&quot;https://img.ly/showcases/cesdk/web/placeholders/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;placeholders&lt;/a&gt; and define &lt;a href=&quot;https://img.ly/showcases/cesdk/web/design-validation/?utm_source=imgly&amp;#x26;utm_medium=blog&amp;#x26;utm_campaign=howtos&quot;&gt;validation rules&lt;/a&gt; to guide your users’ creation process.&lt;/p&gt;
&lt;p&gt;Thanks for reading! We hope that you found this article helpful. Feel free to reach out on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt; with any questions, comments, or suggestions.&lt;/p&gt;</content:encoded><dc:creator>Antonello</dc:creator><media:content url="https://blog.img.ly/2022/09/content-moderation-image-upload.png" medium="image"/><category>How-To</category><category>Automation</category><category>Web Development</category><category>Design Editor</category><category>Image Editing</category><category>Learning</category></item></channel></rss>