> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Retail and e-commerce visual differentiators


This page explores how to leverage Cloudinary to set your brand apart with dynamic and immersive media. Discover strategies for creating personalized assets, automating image-to-video transformations, integrating interactive and 3D product visualizations, and incorporating user-generated content (UGC) to enhance engagement.

## Personalization at scale

Personalized images and videos enhances customer engagement by customizing product visuals based on user preferences, behaviors, and actions. Cloudinary enables brands to dynamically generate personalized assets at scale, improving customer experience and conversion rates. 

Here are some examples of personalized images and videos:

### Custom engraving and branding

Allow the user to select a t-shirt style and color, and enter their name and number. Generate an image with the requested shirt and personalizations. 

> **TIP**:
>
> :title=Tips:

> * This demo allows users to select a custom font for their names. For more information on using custom fonts with Cloudinary, see [Custom fonts](layers#custom_fonts).

> * Depending on the selected T-shirt color, users can also add a shadow effect, implemented by placing an additional black text overlay under the name in the foreground.

Try out this demo app and explore the code: 

> **TIP**: :title=View the code

You can find the code for this sample project in [GitHub](https://github.com/cloudinary-devs/personalize-products).

### Dynamic banners for targeted advertising

Generate personalized sales banners based on browsing history. Here's an example: 

Here's one of the variations shown in the video and the code to create it:

![Dynamic banner](https://cloudinary-res.cloudinary.com/image/upload/c_scale,w_1500/w_850,h_1000,c_fill/c_pad,b_gen_fill,w_850,h_1150,g_south/e_gen_remove:prompt_plate/e_gen_remove:prompt_food/c_fit,co_white,l_text:Arial_85_bold:NEW%20LOCATION,w_600/g_north_west,x_60,y_60,fl_layer_apply/c_fit,co_white,l_text:Arial_75_line_spacing_-10:Treat%20yourself%20just%20around%20the%20corner,w_300/g_east,y_50,x_80,fl_layer_apply/c_fit,co_white,l_text:Impact_95_bold_line_spacing_-10:The%20Cafe%20Coffee,w_450/g_south_east,x_80,y_50,fl_layer_apply/v1742212513/restaurant_banner.jpg "thumb: w_300,dpr_2, width:300, popup:true, with_url:true, with_code:true")

> **TIP**:
>
> * You can use variables instead of hard coding the text so that you can personalize or localize the overlays based on target audience. For more information, see [User-defined variables and arithmetic image transformations](user_defined_variables).

> * Use named transformations to make this URL much more user-friendly. For more information, see [Compare direct transformations to named transformations](ecommerce_optimize_customize#compare_direct_transformations_to_named_transformations).

### Abandoned cart reminders

Automatically send emails reminding users about their abandoned cart, featuring dynamically updated product details to encourage them to complete their purchase.

![Email campaign banner - mobile](https://res.cloudinary.com/demo/image/upload/l_fix/g_west,x_1565,y_72,fl_layer_apply/l_black_heels_bg/c_pad,w_950,h_950,b_auto/r_max/fl_layer_apply,g_west,x_950,y_430/v1742904901/docs/adandoned-cart-mobile.png "thumb: w_500,dpr_2, width:500, popup:true, with_url:true, with_code:true")

```nodejs
cloudinary.image("docs/adandoned-cart-mobile.png", {transformation: [
  {overlay: "fix"},
  {gravity: "west", x: 1565, y: 72, flags: "layer_apply"},
  {overlay: "black_heels_bg"},
  {width: 950, height: 950, background: "auto", crop: "pad"},
  {radius: "max"},
  {flags: "layer_apply", gravity: "west", x: 950, y: 430}
  ]})
```

```react
new CloudinaryImage("docs/adandoned-cart-mobile.png")
  .overlay(
    source(image("fix")).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(1565)
        .offsetY(72)
    )
  )
  .overlay(
    source(
      image("black_heels_bg").transformation(
        new Transformation()
          .resize(pad().width(950).height(950).background(auto()))
          .roundCorners(max())
      )
    ).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(950)
        .offsetY(430)
    )
  )
  .setVersion(1742904901);
```

```vue
new CloudinaryImage("docs/adandoned-cart-mobile.png")
  .overlay(
    source(image("fix")).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(1565)
        .offsetY(72)
    )
  )
  .overlay(
    source(
      image("black_heels_bg").transformation(
        new Transformation()
          .resize(pad().width(950).height(950).background(auto()))
          .roundCorners(max())
      )
    ).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(950)
        .offsetY(430)
    )
  )
  .setVersion(1742904901);
```

```angular
new CloudinaryImage("docs/adandoned-cart-mobile.png")
  .overlay(
    source(image("fix")).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(1565)
        .offsetY(72)
    )
  )
  .overlay(
    source(
      image("black_heels_bg").transformation(
        new Transformation()
          .resize(pad().width(950).height(950).background(auto()))
          .roundCorners(max())
      )
    ).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(950)
        .offsetY(430)
    )
  )
  .setVersion(1742904901);
```

```js
new CloudinaryImage("docs/adandoned-cart-mobile.png")
  .overlay(
    source(image("fix")).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(1565)
        .offsetY(72)
    )
  )
  .overlay(
    source(
      image("black_heels_bg").transformation(
        new Transformation()
          .resize(pad().width(950).height(950).background(auto()))
          .roundCorners(max())
      )
    ).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(950)
        .offsetY(430)
    )
  )
  .setVersion(1742904901);
```

```python
CloudinaryImage("docs/adandoned-cart-mobile.png").image(transformation=[
  {'overlay': "fix"},
  {'gravity': "west", 'x': 1565, 'y': 72, 'flags': "layer_apply"},
  {'overlay': "black_heels_bg"},
  {'width': 950, 'height': 950, 'background': "auto", 'crop': "pad"},
  {'radius': "max"},
  {'flags': "layer_apply", 'gravity': "west", 'x': 950, 'y': 430}
  ])
```

```php
(new ImageTag('docs/adandoned-cart-mobile.png'))
	->overlay(Overlay::source(
	Source::image("fix"))
	->position((new Position())
	->gravity(
	Gravity::compass(
	Compass::west()))
->offsetX(1565)
->offsetY(72))
	)
	->overlay(Overlay::source(
	Source::image("black_heels_bg")
	->transformation((new Transformation())
	->resize(Resize::pad()->width(950)
->height(950)
	->background(
	Background::auto())
	)
	->roundCorners(RoundCorners::max()))
	)
	->position((new Position())
	->gravity(
	Gravity::compass(
	Compass::west()))
->offsetX(950)
->offsetY(430))
	)
	->version(1742904901);
```

```java
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("fix")).chain()
  .gravity("west").x(1565).y(72).flags("layer_apply").chain()
  .overlay(new Layer().publicId("black_heels_bg")).chain()
  .width(950).height(950).background("auto").crop("pad").chain()
  .radius("max").chain()
  .flags("layer_apply").gravity("west").x(950).y(430)).imageTag("docs/adandoned-cart-mobile.png");
```

```ruby
cl_image_tag("docs/adandoned-cart-mobile.png", transformation: [
  {overlay: "fix"},
  {gravity: "west", x: 1565, y: 72, flags: "layer_apply"},
  {overlay: "black_heels_bg"},
  {width: 950, height: 950, background: "auto", crop: "pad"},
  {radius: "max"},
  {flags: "layer_apply", gravity: "west", x: 950, y: 430}
  ])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("fix")).Chain()
  .Gravity("west").X(1565).Y(72).Flags("layer_apply").Chain()
  .Overlay(new Layer().PublicId("black_heels_bg")).Chain()
  .Width(950).Height(950).Background("auto").Crop("pad").Chain()
  .Radius("max").Chain()
  .Flags("layer_apply").Gravity("west").X(950).Y(430)).BuildImageTag("docs/adandoned-cart-mobile.png")
```

```dart
cloudinary.image('docs/adandoned-cart-mobile.png').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("fix"))
	.position(Position()
	.gravity(
	Gravity.compass(
	Compass.west()))
.offsetX(1565)
.offsetY(72))
	)
	.overlay(Overlay.source(
	Source.image("black_heels_bg")
	.transformation(new Transformation()
	.resize(Resize.pad().width(950)
.height(950)
	.background(
	Background.auto())
	)
	.roundCorners(RoundCorners.max()))
	)
	.position(Position()
	.gravity(
	Gravity.compass(
	Compass.west()))
.offsetX(950)
.offsetY(430))
	)
	.version(1742904901));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setOverlay("fix").chain()
  .setGravity("west").setX(1565).setY(72).setFlags("layer_apply").chain()
  .setOverlay("black_heels_bg").chain()
  .setWidth(950).setHeight(950).setBackground("auto").setCrop("pad").chain()
  .setRadius("max").chain()
  .setFlags("layer_apply").setGravity("west").setX(950).setY(430)).generate("docs/adandoned-cart-mobile.png")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("fix")).chain()
  .gravity("west").x(1565).y(72).flags("layer_apply").chain()
  .overlay(new Layer().publicId("black_heels_bg")).chain()
  .width(950).height(950).background("auto").crop("pad").chain()
  .radius("max").chain()
  .flags("layer_apply").gravity("west").x(950).y(430)).generate("docs/adandoned-cart-mobile.png");
```

```flutter
cloudinary.image('docs/adandoned-cart-mobile.png').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("fix"))
	.position(Position()
	.gravity(
	Gravity.compass(
	Compass.west()))
.offsetX(1565)
.offsetY(72))
	)
	.overlay(Overlay.source(
	Source.image("black_heels_bg")
	.transformation(new Transformation()
	.addTransformation())
	)
	.position(Position()
	.gravity(
	Gravity.compass(
	Compass.west()))
.offsetX(950)
.offsetY(430))
	)
	.version(1742904901));
```

```kotlin
cloudinary.image {
	publicId("docs/adandoned-cart-mobile.png")
	 overlay(Overlay.source(
	Source.image("fix")) {
	 position(Position() {
	 gravity(
	Gravity.compass(
	Compass.west()))
 offsetX(1565)
 offsetY(72) })
	 })
	 overlay(Overlay.source(
	Source.image("black_heels_bg") {
	 transformation(Transformation {
	 resize(Resize.pad() { width(950)
 height(950)
	 background(
	Background.auto())
	 })
	 roundCorners(RoundCorners.max()) })
	 }) {
	 position(Position() {
	 gravity(
	Gravity.compass(
	Compass.west()))
 offsetX(950)
 offsetY(430) })
	 })
	 version(1742904901) 
}.generate()
```

```jquery
$.cloudinary.image("docs/adandoned-cart-mobile.png", {transformation: [
  {overlay: new cloudinary.Layer().publicId("fix")},
  {gravity: "west", x: 1565, y: 72, flags: "layer_apply"},
  {overlay: new cloudinary.Layer().publicId("black_heels_bg")},
  {width: 950, height: 950, background: "auto", crop: "pad"},
  {radius: "max"},
  {flags: "layer_apply", gravity: "west", x: 950, y: 430}
  ]})
```

```react_native
new CloudinaryImage("docs/adandoned-cart-mobile.png")
  .overlay(
    source(image("fix")).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(1565)
        .offsetY(72)
    )
  )
  .overlay(
    source(
      image("black_heels_bg").transformation(
        new Transformation()
          .resize(pad().width(950).height(950).background(auto()))
          .roundCorners(max())
      )
    ).position(
      new Position()
        .gravity(compass("west"))
        .offsetX(950)
        .offsetY(430)
    )
  )
  .setVersion(1742904901);
```

### AI-powered color replacement

You can change the color of the product dynamically using Cloudinary’s `e_gen_recolor` transformation.

Here's the original image:

![Original](https://cloudinary-res.cloudinary.com/image/upload/v1741169385/docs/dress_recolor.jpg "thumb: w_350,dpr_2, width:350, popup:true, with_url:false, with_code:false")

Here’s the code to recolor the product to dark green using `39463E`:

![Green](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/e_gen_recolor:prompt_(dress;belt;sash);to-color_39463E;multiple_true/v1741169385/docs/dress_recolor.jpg "thumb: w_350,dpr_2, width:350, popup:true, with_url:true, with_code:true, with_image:false")

To recolor the product in different shades, replace `39463E` with:

* Turquoise → `B7F1F1`
* Grey → `C2C9D6`
* White → `FFFFFF`

Each of these color codes will generate a new variation of the product in the specified shade.

Dark green variation

Turquoise variation

Grey variation

White variation

### Textured images and overlays

Use transparent PNG overlays and underlays for customized textures.

Here's an example of underlaying a leaf image under a product to create texture:

Original product

Textured underlay

Resulting combination

Here's the code to create the underlay:

![Textured product underlay](https://cloudinary-res.cloudinary.com/image/upload/u_green_leaf/g_north_east,fl_layer_apply,x_100/f_auto/q_auto/v1742227313/essential_oil.png "thumb: w_350,dpr_2, width:350, popup:true, with_url:true, with_code:true, with_image:false")

### Background swaps for localized campaign 

Adjust backgrounds to fit different campaign themes and locations. 

This example uses two separate underlays to apply different backgrounds to a transparent image.

Master copy - no background

Office background

Apartments background

Here's the code for adding the office background as an underlay: 

![Background underlay](https://cloudinary-res.cloudinary.com/image/upload/u_docs:office_background/fl_layer_apply/f_auto/q_auto/v1742226399/docs/blue_tshirt.png "with_image:false, with_code:true, with_url:true")

For more advanced background removal and refinement, see [FinalTouch](finaltouch).
  

## Images to videos

E-commerce brands can enhance product presentation by dynamically converting images into engaging videos.

Here are some examples of image-to-video transformations:

### Zoom and pan effect 

Adds movement to static images. 

In this example, watch the `e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40` transformation in action.

![Living room zooming out from center](https://res.cloudinary.com/demo/image/upload/e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40/v1739719225/509583867_cs9acj.mp4 "with_image:false")

```nodejs
cloudinary.video("509583867_cs9acj", {effect: "zoompan:mode_ofl;maxzoom_2;du_8;fps_40", resource_type: "image"})
```

```react
new CloudinaryVideo("509583867_cs9acj.mp4")
  .addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
  .setVersion(1739719225)
  .setAssetType("image");
```

```vue
new CloudinaryVideo("509583867_cs9acj.mp4")
  .addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
  .setVersion(1739719225)
  .setAssetType("image");
```

```angular
new CloudinaryVideo("509583867_cs9acj.mp4")
  .addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
  .setVersion(1739719225)
  .setAssetType("image");
```

```js
new CloudinaryVideo("509583867_cs9acj.mp4")
  .addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
  .setVersion(1739719225)
  .setAssetType("image");
```

```python
CloudinaryImage("509583867_cs9acj").video(effect="zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
```

```php
(new VideoTag('509583867_cs9acj.mp4'))
	->addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
	->version(1739719225)
	->assetType("image");
```

```java
cloudinary.url().transformation(new Transformation().effect("zoompan:mode_ofl;maxzoom_2;du_8;fps_40")).resourceType("image").videoTag("509583867_cs9acj");
```

```ruby
cl_video_tag("509583867_cs9acj", effect: "zoompan:mode_ofl;maxzoom_2;du_8;fps_40", resource_type: "image")
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Effect("zoompan:mode_ofl;maxzoom_2;du_8;fps_40")).BuildVideoTag("509583867_cs9acj")
```

```dart
cloudinary.video('509583867_cs9acj.mp4').transformation(Transformation()
	.addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
	.version(1739719225)
	.setAssetType("image"));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setEffect("zoompan:mode_ofl;maxzoom_2;du_8;fps_40")).generate("509583867_cs9acj.mp4")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().effect("zoompan:mode_ofl;maxzoom_2;du_8;fps_40")).generate("509583867_cs9acj.mp4");
```

```flutter
cloudinary.video('509583867_cs9acj.mp4').transformation(Transformation()
	.addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
	.version(1739719225)
	.setAssetType("image"));
```

```kotlin
cloudinary.video {
	publicId("509583867_cs9acj.mp4")
	 addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
	 version(1739719225)
	 assetType("image") 
}.generate()
```

```jquery
$.cloudinary.video("509583867_cs9acj", {effect: "zoompan:mode_ofl;maxzoom_2;du_8;fps_40", resource_type: "image"})
```

```react_native
new CloudinaryVideo("509583867_cs9acj.mp4")
  .addTransformation("e_zoompan:mode_ofl;maxzoom_2;du_8;fps_40")
  .setVersion(1739719225)
  .setAssetType("image");
```

  
    
    
    
  
  

For more information, see the zoompan method of the Transformation API and read the Add Motion to Your Pictures blog post.

### Sample project: Product color change animation 

You can create a product showcase animation with multiple color variations using Cloudinary’s Upload API. This example dynamically recolors a single product image, turns it into a GIF, and then converts it to MP4 for better performance and compatibility.

This demo goes a step further by adding custom text and image overlays for an engaging branded animation:

    
    Your browser does not support the video tag.

> **TIP**: :title=Go to the code

Check out the full project on [GitHub](https://github.com/cloudinary-devs/product-recolor-animation).

Setup instructions (after cloning from GitHub)

1. **Create a virtual environment**
   
    ```Terminal
    python3 -m venv venv
    ```

2. **Activate your virtual environment**
   
    ```Terminal
    source venv/bin/activate
    ```

3. **Install dependencies**
   
    ```Terminal
    pip install -r requirements.txt
    ```

4. **Create a `.env` file**
   Add the following environment variable:
  
    ```python
    CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
    ``` 
   
5. **Replace placeholders**
   Update the `.env` file with your Cloudinary credentials, which you can find in the [API Keys](https://console.cloudinary.com/app/settings/api-keys) page of the Console Settings.
   
6.  **Run the Flask app**
    
    ```Terminal
    python demo.py
    ```

What the code does

1. In the `server.py` file, generate different color variations of the product using Cloudinary’s `e_gen_recolor` transformation and store them in an array of image URLs.
2. Call the [multi](image_upload_api_reference#multi) endpoint of the Upload API to generate the GIF.
3. Convert the GIF URL to MP4 to improve performance.
4. Upload the video to Cloudinary.
5. Add text and branding elements as overlays.

## Interactive video experiences

Interactive videos engage customers more effectively than static product images. Cloudinary enables brands to add overlays, clickable elements, and tracking effects.

Here are some examples of interactive video experiences:

### Shoppable video overlays 

Let customers click on items within a video to explore or purchase them. 

Click the video below to see the UI in action:

Here's the source code for this video

```javascript
<div style="width: 250px; margin: auto;">
<video id="player" controls muted class="cld-video-player cld-fluid"></video>
</div>

<script>
  
const player = cloudinary.videoPlayer('player', { cloudName: 'demo', interactionDisplay: true});

const sources = {
        top:'https://res.cloudinary.com/demo/video/upload/docs/my_video_top_zoom.mp4',
        middle:'https://res.cloudinary.com/demo/video/upload/docs/my_video_middle_zoom.mp4',
        bottom:'https://res.cloudinary.com/demo/video/upload/docs/my_video_bottom_zoom.mp4'
      }

player.source('docs/my_video', {
  interactionAreas: {
      enable: true,
      template: 'portrait',
      onClick: function(event) {
          event.zoom(sources[event.item.id]); 
      }
  }
});
```

For more information, see [Video zoom](video_player_interactive_videos#video_zoom).

### Object tracking

Ensure product highlights move dynamically with items in a video.

In this example, the `top` object is being detected, the layer is positioned `west` of the person ensuring that it's always visible, and the size adapts to always be 50% sized relative to the tracked person:

![Adding a layer that tracks a person wearing a top](https://res.cloudinary.com/demo/video/upload/l_sale_overlay_box/g_track_person:obj_top;position_w;adaptivesize_50,fl_layer_apply/v1742249264/model_photo_shoot.mp4 "width: 500, with_code: true, poster: https://res.cloudinary.com/cloudinary/video/upload/model_photo_shoot.jpg")

```nodejs
cloudinary.video("model_photo_shoot", {transformation: [
  {overlay: "sale_overlay_box"},
  {gravity: "track_person:obj_top;position_w;adaptivesize_50", flags: "layer_apply"}
  ]})
```

```react
new CloudinaryVideo("model_photo_shoot.mp4")
  .overlay(
    source(image("sale_overlay_box")).position(
      new Position().gravity(
        focusOn("track_person", "obj_top;position_w;adaptivesize_50")
      )
    )
  )
  .setVersion(1742249264);
```

```vue
new CloudinaryVideo("model_photo_shoot.mp4")
  .overlay(
    source(image("sale_overlay_box")).position(
      new Position().gravity(
        focusOn("track_person", "obj_top;position_w;adaptivesize_50")
      )
    )
  )
  .setVersion(1742249264);
```

```angular
new CloudinaryVideo("model_photo_shoot.mp4")
  .overlay(
    source(image("sale_overlay_box")).position(
      new Position().gravity(
        focusOn("track_person", "obj_top;position_w;adaptivesize_50")
      )
    )
  )
  .setVersion(1742249264);
```

```js
new CloudinaryVideo("model_photo_shoot.mp4")
  .overlay(
    source(image("sale_overlay_box")).position(
      new Position().gravity(
        focusOn("track_person", "obj_top;position_w;adaptivesize_50")
      )
    )
  )
  .setVersion(1742249264);
```

```python
CloudinaryVideo("model_photo_shoot").video(transformation=[
  {'overlay': "sale_overlay_box"},
  {'gravity': "track_person:obj_top;position_w;adaptivesize_50", 'flags': "layer_apply"}
  ])
```

```php
(new VideoTag('model_photo_shoot.mp4'))
	->overlay(Overlay::source(
	Source::image("sale_overlay_box"))
	->position((new Position())
	->gravity(
	Gravity::focusOn("track_person","obj_top;position_w;adaptivesize_50"))
	)
	)
	->version(1742249264);
```

```java
cloudinary.url().transformation(new Transformation()
  .overlay(new Layer().publicId("sale_overlay_box")).chain()
  .gravity("track_person:obj_top;position_w;adaptivesize_50").flags("layer_apply")).videoTag("model_photo_shoot");
```

```ruby
cl_video_tag("model_photo_shoot", transformation: [
  {overlay: "sale_overlay_box"},
  {gravity: "track_person:obj_top;position_w;adaptivesize_50", flags: "layer_apply"}
  ])
```

```csharp
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Overlay(new Layer().PublicId("sale_overlay_box")).Chain()
  .Gravity("track_person:obj_top;position_w;adaptivesize_50").Flags("layer_apply")).BuildVideoTag("model_photo_shoot")
```

```dart
cloudinary.video('model_photo_shoot.mp4').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("sale_overlay_box"))
	.position(Position()
	.gravity(
	Gravity.focusOn("track_person","obj_top;position_w;adaptivesize_50"))
	)
	)
	.version(1742249264));
```

```swift
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setOverlay("sale_overlay_box").chain()
  .setGravity("track_person:obj_top;position_w;adaptivesize_50").setFlags("layer_apply")).generate("model_photo_shoot.mp4")
```

```android
MediaManager.get().url().transformation(new Transformation()
  .overlay(new Layer().publicId("sale_overlay_box")).chain()
  .gravity("track_person:obj_top;position_w;adaptivesize_50").flags("layer_apply")).resourceType("video").generate("model_photo_shoot.mp4");
```

```flutter
cloudinary.video('model_photo_shoot.mp4').transformation(Transformation()
	.overlay(Overlay.source(
	Source.image("sale_overlay_box"))
	.position(Position()
	.gravity(
	Gravity.focusOn("track_person","obj_top;position_w;adaptivesize_50"))
	)
	)
	.version(1742249264));
```

```kotlin
cloudinary.video {
	publicId("model_photo_shoot.mp4")
	 overlay(Overlay.source(
	Source.image("sale_overlay_box")) {
	 position(Position() {
	 gravity(
	Gravity.focusOn("track_person","obj_top;position_w;adaptivesize_50"))
	 })
	 })
	 version(1742249264) 
}.generate()
```

```jquery
$.cloudinary.video("model_photo_shoot", {transformation: [
  {overlay: new cloudinary.Layer().publicId("sale_overlay_box")},
  {gravity: "track_person:obj_top;position_w;adaptivesize_50", flags: "layer_apply"}
  ]})
```

```react_native
new CloudinaryVideo("model_photo_shoot.mp4")
  .overlay(
    source(image("sale_overlay_box")).position(
      new Position().gravity(
        focusOn("track_person", "obj_top;position_w;adaptivesize_50")
      )
    )
  )
  .setVersion(1742249264);
```

For more information, see [Dynamic video overlays](video_layers#dynamic_video_overlays).

## 3D and immersive experiences

Cloudinary supports 3D product visualization and immersive content to help brands stand out.

Here are some examples of 3D and immersive experiences:

### Increase work efficiency

Render high-quality 2D product images from 3D models for marketing use, reducing the need for traditional photography. Utilize 3D renders as design blueprints that you can share with manufacturers.

### Enable 360° spin views

Display interactive product views using Cloudinary's [Product Gallery Widget](product_gallery). 

### View in augmented reality

Deliver 3D previews for mobile and augmented reality commerce with Cloudinary's [Product Gallery Widget](product_gallery).

Here's an example of a product gallery displaying a 3D model of a red sneaker. You can inspect the product from all angles or view it in AR:

 
 
   
     AR Instructions
     Scan this QR code with your mobile device to view in AR
     
     
     Close
   
 

  

## User-generated content (UGC)

Brands use UGC to increase engagement and conversions. Cloudinary helps manage UGC efficiently.

### Common uses of UGC in e-commerce

* Customer reviews and ratings
* User-submitted images and videos
* Social media content (e.g., Instagram hashtags or posts)
* Testimonials and product usage images and videos

### Cloudinary features for UGC

* **Upload Widget**: Provides a simple interface for customers to upload assets.
* **Moderation tools**: Ensure content meets brand guidelines.
* **AI-powered transformations**: Auto-crop, resize, and enhance assets dynamically.
* **Optimization**: Improve loading speed with automatic compression and formatting.

For more information about handling UGC, see [User-generated content](user_generated_content).

 

  

