> ## 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.

# Non-product asset workflows


This section provides an example workflow for managing non-product assets, also known as editorial, content, or brand assets. Use these recommendations as a foundation and adapt the implementation to fit your company’s needs.

Unlike product assets, non-product assets—such as hero images, marketing videos, social media content, and promotional materials—are often curated to shape the overall experience. These assets typically require manual selection, approval, and refinement. As an administrator, you may handle setup and automation, while content editors focus on editing and selecting assets for the website and other delivery channels.

![Non-product asset workflows](https://cloudinary-res.cloudinary.com/image/upload/q_auto/f_auto/v1743596946/docs/non_product_workflow.png "thumb: w_803,dpr_2, width:803, popup:true")

## Enrich and organize on upload

Handle setup tasks such as creating folders, configuring auto-tagging, managing accessibility settings, and enforcing access restrictions. Meanwhile, content editors manually upload assets via the Media Library within Cloudinary’s Assets (DAM) product. Contributors select and upload images and videos for storytelling, branding, and marketing, adding metadata as needed.

In this section, you'll learn how to set up and upload non-product assets in the Media Library.

### Step 1: Create folder structure
Start by organizing your non-product assets—such as brand logos, marketing images, video content, or internal documentation—into a clear folder structure. This improves searchability and asset management, and is especially important because permissions and governance in the Media Library are enforced through folder structure.

We recommend starting with a root folder like `non_product_assets/`, and organizing by purpose or content type.

Here's a sample folder structure for non-product assets:

```
non_product_assets/
  brand/
    logos/
    guidelines/
  marketing/
    campaigns/
    social_media/
  events/
    2024_launch/
    trade_shows/
  internal/
    presentations/
    reference_materials/
```
**To create a folder:**

1. Click the **Folders** tab at the top of the Media Library to navigate to that page.
2. Click the **Create a Folder** icon at the top left corner. 
3. To create a subfolder, navigate to the parent folder first.

![Create a folder](https://cloudinary-res.cloudinary.com/image/upload/c_crop,w_400,h_145,g_south_west/f_auto/q_auto/bo_1px_solid_grey/docs/DAM/create_folder.png "thumb: w_300,dpr_2, width:300, popup:true")
#### Sharing folders with Media Library users

While developers on your team may have **Admin** user roles, you should assign **Media Library user** roles to content editors in your organization who work with assets within the Media Library. For more information on adding users and assigning roles, see [User and group management](dam_admin_users_groups). 

Media Library users won't be able to view any content in the Media Library until you share folders with them. Once you do that, they'll be able to access the assets within the folder and its subfolders at the permission level you assign.

**To share a folder:**

1. Select **Share** from the options drop-down next to the current folder path at the top of the Media Library 
  ![Folder path drop-down](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1739201555/docs/DAM/folder_toolbar_expanded_new.png "thumb: w_200,dpr_2, width:250, with_url:false, with_code:false, popup:true")
2. Select the users and/or user groups you want to share the folder with, as well as the permission level for each. 

For more information, see [Folder management](dam_folders_collections_sharing#folder_management).

### Step 2: Register for add-ons
In order to enable some upload preset options, you first need to register for Cloudinary's [add-ons](https://console.cloudinary.com/app/settings/addons). You'll then activate the selected add-ons using upload preset options in [Step 3](#step_3).

Here are some of the add-ons you may want to apply:

{table:class=no-borders overview}Add-on | What it Does | Considerations | Implementation  
---|---|---|---  
| **Google Auto Tagging** | Automatically tags images using Google Vision AI. | Works well for general **object recognition** and **categorization**. | 1 - Register for the **Google Auto Tagging** add-on in the [Add-ons](https://console.cloudinary.com/app/settings/addons) page.  2 - Enable **Google Auto Tagging** in **Addons** page of a new upload preset.  |  
| **Amazon Rekognition Auto Tagging** | Detects objects and assigns tags using Amazon Rekognition. | Useful for AI-powered **object detection and scene analysis**. | 1 - Register for the **Amazon Rekognition Auto Tagging** add-on.  2 - Enable **Rekognition Auto Tagging** in the **Addons** page of a new upload preset.  |  
| **Auto Moderation** | Flags inappropriate content. | Ideal for **content moderation** and **brand safety**. | 1 - Register for the **Rekognition AI Moderation** and **Rekognition AI Video Moderation** add-on.  2 - Enable **Rekognition AI Moderation** (for images) or **Rekognition AI Video Moderation** (for videos) in the **Addons** page of a new upload preset.  |  
| **Cloudinary AI Content Analysis** | Generates image captions and auto-tags assets. | Useful for **automatic alt text** and **SEO improvements**. | 1 - Register for the **Cloudinary AI Content Analysis** add-on.  2 - Enable **Add AI captioning to your image** for the **Cloudinary AI Content Analysis** add-on in the **AI media processing**  section in the **Addons** page of a new upload preset.  |  
| **Google Video Intelligence** | Labels objects and scenes in videos. | Ideal for **video content classification**. | 1 - Register for the **Google Video Intelligence** add-on.  2 - Enable **Google Automatic Video Tagging** in the **Addons** page of a new upload preset.  |  
| **Google Translation** | Translates video transcription into multiple languages. (You don't need to register for an add-on to activate Cloudinary's transcription functionality, but you do need to register for the add-on for translation.) | Enhances **accessibility**, **SEO**, and **multi-language support**. | 1 - Register for the **Google Translation** add-on.  2 - Enable **Auto transcription** and **Translate**, and select a language in the **Manage and Analyze** page of a new upload preset. |  

### Step 3: Use an upload preset for auto-tagging, alt-text, and access control
You can create upload presets, which centrally define a set of asset upload options. Users can apply the options by applying the presets on upload to improve accessibility, streamline searchability, and enforce asset restrictions.
                        

**To create an upload preset to apply upload options:**

* Navigate to the [Upload Presets](https://console.cloudinary.com/app/settings/upload/presets) tab on the **Upload** page of the Console Settings and click **Add Upload Preset**.
* Use the table below to apply recommended upload preset options, see how they align with best practices, and learn how to implement them.

{table:class=wide-lastcol-img no-borders overview}Option | How it Supports Best Practices | Implementation
---|---|---
| Naming and [folder location](#step_1) | Enforces naming conventions within your organization. Enforces governance within the organization and improves discoverability by uploading assets to meaningful folder locations. | In the **General** tab of the new upload preset:  - Enter the name of the **Asset folder** you want to upload to. - Select **Use the filename of the uploaded file as the public ID** to enforce naming conventions when the uploaded file contains the SKU. **Note:** If the SKU isn't part of the uploaded file's name and the SKU needs to be part of the public ID, set the SKU as a `public_id_prefix` using a variable representing the `SKU`. However, you can only do this by configuring the upload preset programmatically. For more information, see [Upload preset](upload_presets#managing_upload_presets_programmatically)![Upload preset - asset naming](https://cloudinary-res.cloudinary.com/image/upload/q_auto/f_auto/bo_1px_solid_grey/v1740940042/docs/upload_preset_product_general.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true")|
| **Improve image and video performance** | Prepares responsive images for various viewports and uses auto-format and quality settings to make sure your website [loads quickly](ecommerce_best_practices#optimize_image_and_video_performance).Warms up the cache by generating the specified transformations on upload, before the assets are actually requested. | In the **Transform** tab of the new upload preset, add `f_auto/q_auto` as [Eager transformations](eager_and_incoming_transformations#eager_transformations) for various viewport sizes, e.g., `w_320`, `w_768`, `w_1280`, `w_1600`.![Upload preset - eager](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1740920187/docs/upload_preset_eager.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true") | 
| **Enhance searchability with auto-tagging** |  [Categorizes](ecommerce_best_practices#enhance_searchability_with_metadata) assets accurately for faster search and retrieval while reducing manual effort. | In the **Addons** tab of the new upload preset, select the auto-tagging add-on(s). Make sure you're registered for those add-ons, as described in [Step 4](#step_4).![Upload preset - auto-tagging](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1740920148/docs/upload_preset_auto_tagging.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true") |  
| **Restrict access to assets with time based availability** | Ensures [sensitive assets](ecommerce_best_practices#manage_asset_rights_and_compliance) are only available when needed.  |  In the **Optimize and Deliver** tab of the new upload preset, set **Access control** to **Restricted**, with an optional date range for unrestricted availability.![Upload preset - access control](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1740920173/docs/uploal_preset_access_control.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true")
| **Auto-generate captions** | Creates captions that you can use as [alt text](ecommerce_best_practices#enhancing_accessibility_with_alt_text) to make images accessible to visually impaired users and improve SEO. | In the **Addons** tab of the new upload preset, select **Add Al captioning to your image** from the **Cloudinary Al Content Analysis** add-on. Make sure you're registered for the **Cloudinary AI Content Analysis** add-on, as described in [Step 5](#step_5).![Upload preset - auto-captioning](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1740920640/docs/upload_preset_captioning.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true") To add the caption to a previously created structured metadata field called **Caption** (whose external_id is `auto_caption`) and add the value *autocaption* to the assets' tags, add the following code in the **On success** script section of the **Advanced** tab of your upload preset:`current_asset.update({tags: ['autocaption'], metadata: {auto_caption: e.upload_info?.info?.detection?.captioning?.data?.caption}})`![Upload preset - auto caption eval](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1743597869/docs/auto_caption_eval_upload_preset.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true") Retrieve the structured metadata field value for an asset and assign it to its alt text when rendering it in your HTML code.|  
| **Generate video transcription and translations**| Provides [video transcription and translation](ecommerce_best_practices#improving_video_accessibility_with_transcripts_and_subtitles) to make videos accessible to deaf and hard-of-hearing users and expand reach to multilingual audiences. | In the **Manage and Analyze** tab of the new upload preset, turn on **Auto transcription** and select the languages you want to provide. Make sure you're registered for the **Video Transcription and Translation** add-on , as described in [Step 4](#step_4).![Upload preset - transcription](https://cloudinary-res.cloudinary.com/image/upload/v1740920227/docs/upload_preset_transcription.png "thumb: w_550,dpr_2, width:550, with_code:false, with_url:false, popup:true") |

* Remember to click **Save** at the top left corner.
  
> **TIP**: You can also manage upload presets programmatically using the [upload_presets](admin_api#upload_presets) endpoint in the Admin API, although using the [Upload](https://console.cloudinary.com/app/settings/upload/presets) page in the Console Settings might be more convenient. You can configure upload presets with any of the parameters available for a regular [upload](image_upload_api_reference#upload) call.

### Step 3: Set up metadata for searchability

To ensure assets are easily searchable and properly categorized, identify which metadata fields are relevant for your non-product assets and then create structured metadata fields. Configure Cloudinary to prompt users for metadata entry on every upload.

**To define metadata in the Media Library**:

1. Go to the [Structured Metadata](https://console.cloudinary.com/console/media_library/metadata_fields) page in the Console.
2. Configure the following metadata options:
  * **Field types**: Text, number, date, single-selection, and multiple-selection lists.
  * **Mandatory fields**: Define required fields to ensure consistent metadata entry. (Make sure you set a realistic number of mandatory fields so your users don't get overwhelmed.)
  * **Default values**: Assign default values to mandatory fields to prevent upload failures.
  * **List values**: Specify predefined values for single and multiple-selection fields.
  * **Metadata rules**: Set conditional rules (e.g., **State** field appears only if **Country** is **US**).![Create and manage structured metadata fields](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1739206430/docs/smd_create_ecommerce.png "thumb: w_800,dpr_2, width:800, popup:true")For more information, see Structured metadata.

### Step 4: Manual upload via the Media Library

Content editors can manually upload assets while applying auto-tagging, automatic alt text generation, and video transcription and translation during the upload process by using an upload preset.
* **Default upload preset**: You can set up [Media Library Upload Preset Defaults](https://console.cloudinary.com/app/settings/c-fb59c6294cba357effd99e13a776a7/upload/defaults) for your images and videos. Select an upload preset that will apply to all uploads performed from the Media Library, whether the upload is done by dragging and dropping into the Media Library or via the Upload Widget by clicking the **Upload** button.

* **Upload preset selection**: For flexibility in selecting upload presets, you can click **Upload** to launch the Upload Widget, then select an Upload Preset in the **Advanced** section and select the appropriate preset from the **Upload Preset** drop-down.

![Upload Widget - select upload preset](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1739205001/docs/upload_widget_nonproduct_preset.png "thumb: w_500,dpr_2, width:500, popup:true")

* **Require metadata on upload**: In the [Upload](https://console.cloudinary.com/console/media_library/preferences/upload) page of the Preferences, select **Always** for the **Request metadata on upload**. When that setting is enabled, Cloudinary prompts filling in metadata field values before finalizing the upload.

![Metadata on upload](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1643036445/docs/DAM/upload_new_flow.png "thumb: w_300,dpr_2, width:300, with_code:false, with_url:false, popup:true")

> **NOTE**:
>
> Depending on our setup, upload presets might not be available in the Upload widget, and the **Request metadata on upload** setting may not be available. For more information, [contact support](https://support.cloudinary.com/hc/en-us/requests/new).
> **TIP**:
>
> You can update metadata for assets that are already uploaded:

> * Bulk set metadata in the Media Library by selecting the assets you want to update and selecting **Edit Structured Metadata** from the assets toolbar, or individually from the [Metadata](dam_manage_metadata#setting_custom_metadata_values) tab of the asset management drill-down page.

> * Update metadata programmatically using the [explicit](image_upload_api_reference#explicit) method.

## Creative approval

Ensure brand consistency and quality control by using a structured approval process for non-product assets before distribution. Cloudinary's **creative approval** workflow streamlines proofing, collaboration, and final approval.

Cloudinary's approval process consists of:

* **Approval flows**: Configurable multi-step workflows that define the review stages assets must pass through before approval.

* **Proofs**: A collection of assets assigned to an approval flow for structured review and approval.

To enforce approvals, create a proof, apply an approval flow, and iterate on assets until final approval.

#### Key benefits

* **Streamlined approvals**: Assign specific reviewers and enforce stage-based approval sequences.

* **Integrated editing and retouching**: Apply transformations and enhancements during the approval process.

* **Structured proofing**: Ensure thorough review before distribution.

> **READING**:
>
> :no-title
> **Enterprise plans**: 

> * **Creative approval** is a premium offering for our **Assets** product. Availability depends on your account setup and incurs an additional cost. If **creative approval** is not yet enabled for your account and you'd like to enable it, please contact your Customer Success Manager.
> **Free plan**: 

> * This feature is unavailable on the **Assets Free** plan. For more options and information, [contact us](https://cloudinary.com/contact).

> **INFO**: Only administrators can create approval flows. However, Media Library users with the appropriate permissions can start a new proof with an approval flow.

For more information on how to create and manage creative approval, see [Creative approval flows](dam_admin_creative_approval_flows) and [Proofs](dam_creative_approval_proofs).

## Customize and optimize on delivery

Create named transformations programmatically or using the Transformation Builder to optimize, resize assets, and apply overlays or effects. We recommend using named transformations over direct transformations as they shorten URLs for better SEO, are easy to reuse, and are simpler to apply when given meaningful names.

After you create the named transformation, you can: 

* **Apply it directly to transform an asset**. For example, the following example applies the `billboard_ad` named transformation to the `restaurant_banner` image:![Apply named transformation](https://cloudinary-res.cloudinary.com/image/upload/t_billboard_ad/restaurant_banner.jpg "thumb: w_250,dpr_2, width:250, with_code:true, with_url:true, with_image:true, popup:true")

* **Associate them with components in your CSM**, so that no matter which image or video content editors select for that area of the website, those visuals get handled according to design requirements.

> **TIP**:
>
> * If a transformation is short and not going to be reused, you can apply it directly to the asset instead of creating a named transformation.

> * You can use variables in the transformation, whether you apply them directly or as named transformations. For example, if you want to localize text overlays or switch out [generative AI](ai_in_action) prompts for specifying background requests or objects for removal. For more information, see the [Transformation reference](transformation_reference) and [User-defined variables and arithmetic image transformations](user_defined_variables).

For more information about creating named transformations to customize assets on delivery, see [Customize and optimize on delivery](ecommerce_optimize_customize).

## Deliver assets to websites

When delivering assets from Cloudinary, your approach depends on whether you’re using an integrated CMS, a custom CMS integration, or a standalone front-end. Each scenario has different methods for inserting and optimizing assets while ensuring a seamless content workflow.

The table below outlines the key differences between these three approaches and how Cloudinary fits into each:

{table:class=no-borders overview}Scenario | How to Use Cloudinary | Best for
---|---|---
| [Delivering assets through an integrated CMS](#delivering_assets_through_an_integrated_cms) | The CMS has a built-in Cloudinary integration, allowing users to browse, search, and insert assets directly from the CMS interface via the Media Library Widget. | Content editors using CMS platforms like WordPress, Contentful, or Shopify. For a full listing, see [Integrations](integrations).
| [Building a custom CMS integration for asset delivery](#building_a_custom_cms_integration_for_asset_delivery) | You need to embed the Media Library Widget in your CMS to provide Cloudinary's asset management features without switching platforms. | Teams using a CMS that doesn’t have a native Cloudinary integration.
| [Delivering assets to a front-end without a Cloudinary integration](#delivering_assets_to_a_front_end_without_a_cloudinary_integration) | Retrieve asset programmatically using Cloudinary’s APIs and deliver them via dynamic URLs with transformations. | Developers building static sites, SPAs, custom applications, or headless front ends.

In the following sections, we’ll walk through how to delivery assets with Cloudinary for each of these methods.

### Delivering assets through an integrated CMS

Once you've set up the transformations for optimization and personalization for the various types of content, the content editors handle asset insertion within the CMS.

#### Insert a personalized asset

If your CMS integrates with Cloudinary, you can access the Media Library directly from your CMS interface, making it easy to insert assets into website content.

1. When adding an image or video to your CMS, select the Cloudinary Media Library to browse available assets.
2. Select from the [search methods](dam_media_asset_search) available in the **Advanced Search** drop-down to find the asset you want to generate variations for.
3. Double click the asset you want to insert to open the manage page. 
4. Find the template you want to use for delivery and click **Insert**.
   > **NOTE**: For a named transformations to be available as templates in the Media Library, you need to enable it as described in [Creating named transformations using the Transformation Builder](#creating_named_transformations_using_the_transformation_builder).
 
![Insert template](https://cloudinary-res.cloudinary.com/image/upload/f_auto/q_auto/bo_1px_solid_grey/v1739317533/docs/select_template.png "thumb: w_700,dpr_2, width:700, with_code:false, with_url:false, popup:true")

### Building a custom CMS integration for asset delivery

If your CMS doesn’t have a built-in Cloudinary integration, you can embed the Media Library Widget to access Cloudinary's Media Library directly from your CMS interface. This allows seamless asset management without switching between platforms.

To integrate Cloudinary into your tech stack, embed the [Media Library Widget](media_library_widget) within your CMS.

#### Example implementation

The following [code sandbox](https://stackblitz.com/~/github.com/cloudinary-devs/media-library-widget-demo?file=index.html) demonstrates how to integrate the Media Library Widget in HTML without using an `iframe`:

This code is also available in [GitHub](https://github.com/cloudinary-devs/media-library-widget-demo).

> **NOTE**: Due to CORS issues with StackBlitz, you may encounter errors when opening the widget after forking the code sandbox. Use the GitHub link below to run it locally instead.

Once this integration is complete, follow the instructions in [Delivering assets through an integrated CMS](#delivering_assets_through_an_integrated_cms) to insert your assets.

### Delivering assets to a front-end without a Cloudinary integration

If you use a front-end that's not integrated with Cloudinary, you can use programmatically integrate Cloudinary functionalities using one of our back-end SDKs.

#### Step 1: Find the assets

* [Search API method](search_method): Query assets using a Lucene-like expression syntax for precise filtering and retrieval. **Example:** Find images tagged with 'hero_image', uploaded within the last day, and exceeding 1 MB in size. In the response, sort the results by `public_id` in descending order, and limit the returned results to 30 assets:

    ```multi
    |ruby
    result = Cloudinary::Search
      .expression('resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m')
      .sort_by('public_id','desc')
      .max_results(30)
      .execute

    |php_2
    $result = $cloudinary->searchApi()
      ->expression('resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m')
      ->sortBy('public_id','desc')
      ->maxResults(30)
      ->execute();

    |python
    result = cloudinary.Search()\
      .expression("resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m")\
      .sort_by("public_id","desc")\
      .max_results("30")\
      .execute()

    |nodejs
    cloudinary.v2.search
      .expression('resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m')
      .sort_by('public_id','desc')
      .max_results(30)
      .execute()
      .then(result=>console.log(result));
      
    |java
    result = cloudinary.search()
      .expression("resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m")
      .sortBy("public_id","desc")
      .maxResults(30)
      .execute();

    |csharp
    SearchResult result = cloudinary.Search()
      .Expression("resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m")
      .SortBy("public_id","desc")
      .MaxResults(30)
      .Execute();

    |go
    resp, err := cld.Admin.Search(ctx, search.Query{
        Expression: "resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m",
        SortBy:     []search.SortByField{{"public_id": "desc"}},
        MaxResults: 30})

    |curl
    curl \
      -H "Content-Type: application/json" \
      -d '{
            "expression": "resource_type:image AND tags=hero_image AND uploaded_at>1d AND bytes>1m",
            "sort_by": [{"public_id": "desc"}],
            "max_results":30
          }' \
      https://<API_KEY>:<API_SECRET>@api.cloudinary.com/v1_1/<cloud_name>/resources/search

    |cli
    cld search "resource_type=image AND tags=hero_image AND uploaded_at>1d AND bytes>1m" -s public_id desc -n 30 
    ```

* The [resources](admin_api#get_details_of_a_single_resource_by_public_id) endpoint of the Admin API: Retrieve the asset's secure delivery URL using the asset's public ID.
  
    ```multi
    |curl
    curl -u <API_KEY>:<API_SECRET> https://api.cloudinary.com/v1_1/<cloud_name>/resources/image/upload/main_hero | jq -r '.secure_url'

    |ruby
    result = Cloudinary::Api.resource('main_hero')
    secure_url = result["secure_url"]

    |php_2
    $result = $api->asset("main_hero");
    $secure_url = $result['secure_url'];

    |python
    result = cloudinary.api.resource("main_hero")
    secure_url = result["secure_url"]

    |nodejs
    cloudinary.v2.api.resource('main_hero')
      .then(result => {
        const secure_url = result.secure_url;
        console.log(secure_url);
      });

    |java
    result = api.resource("main_hero", ObjectUtils.emptyMap());
    String secureUrl = result.get("secure_url").toString();

    |csharp
    var result = cloudinary.GetResource("main_hero");
    var secureUrl = result.SecureUrl;

    |go
    resp, err := cld.Admin.Asset(ctx, admin.AssetParams{PublicID: "main_hero"})
    if err == nil {
        secureUrl := resp.SecureURL
    }

    |cli
    cld admin resource main_hero --json | jq -r '.secure_url'
    ```

* [Admin API visual search method](admin_api#visual_search_for_resources): Locate images based on visual similarity rather than text-based metadata.**Example**: Execute a visual search for 'footwear':

    ```multi      
    |ruby
    Cloudinary::Api.visual_search(text: "footwear")

    |php_2
    $api->visualSearch("text" => "footwear");

    |python
    cloudinary.api.visual_search(text = "footwear")

    |nodejs
    cloudinary.v2.api.visual_search({text: "footwear"}).then(callback);

    |java
    cloudinary.api().visualSearch(ObjectUtils.asMap(
      "text", "footwear"
    ));

    |csharp
    var info = cloudinary.VisualSearch(new VisualSearchParams{
      Text = "footwear"
    });

    |go
    resp, err := cld.Admin.VisualSearch(ctx, admin.VisualSearchParams{
   	  Text: "footwear"
    })

    |cli
    cld admin visual_search text="footwear"

    |curl
    curl https://<API_KEY>:<API_SECRET>@api.cloudinary.com/v1_1/<cloud_name>/resources/visual_search?text="footwear"
    ```

* Here's a sample response containing some of the returned fields:

    ```json
    {
      "next_cursor": "a36b8bd80426df43a107f26b0348",
      "resources": [
      {
        "asset_id": "5f9d30acd36ac3c4f48a82241a37a299",
        "public_id": "summer-collection-hero",
        …
        …
      },
      {
        "asset_id": "191ad30acd36acf48a82241a137a299a",
        "public_id": "spring-sale-hero",
        …
        …
      }
      …
    }
    ```

#### Step 2: Customize and deliver

Once you've selected the asset to fit into the component, apply the named transformation to it.

1. Use an SDK helper method to generate the HTML image tag that includes the delivery URL for the `docs/winter_fashion` image with the `dark_text_overlay` named transformation applied:![Hero image](https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay/docs/winter_fashion.jpg "thumb: w_500,dpr_2, width:500, popup:true")

```nodejs
cloudinary.image("docs/winter_fashion.jpg", {transformation: ["dark_text_overlay"]})
```

```react
new CloudinaryImage("docs/winter_fashion.jpg").namedTransformation(
  name("dark_text_overlay")
);
```

```vue
new CloudinaryImage("docs/winter_fashion.jpg").namedTransformation(
  name("dark_text_overlay")
);
```

```angular
new CloudinaryImage("docs/winter_fashion.jpg").namedTransformation(
  name("dark_text_overlay")
);
```

```js
new CloudinaryImage("docs/winter_fashion.jpg").namedTransformation(
  name("dark_text_overlay")
);
```

```python
CloudinaryImage("docs/winter_fashion.jpg").image(transformation=["dark_text_overlay"])
```

```php
(new ImageTag('docs/winter_fashion.jpg'))
	->namedTransformation(NamedTransformation::name("dark_text_overlay"));
```

```java
cloudinary.url().transformation(new Transformation().named("dark_text_overlay")).imageTag("docs/winter_fashion.jpg");
```

```ruby
cl_image_tag("docs/winter_fashion.jpg", transformation: ["dark_text_overlay"])
```

```csharp
cloudinary.Api.UrlImgUp.Transform(new Transformation().Named("dark_text_overlay")).BuildImageTag("docs/winter_fashion.jpg")
```

```dart
cloudinary.image('docs/winter_fashion.jpg').transformation(Transformation()
	.namedTransformation(NamedTransformation.name("dark_text_overlay")));
```

```swift
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setNamed("dark_text_overlay")).generate("docs/winter_fashion.jpg")!, cloudinary: cloudinary)
```

```android
MediaManager.get().url().transformation(new Transformation().named("dark_text_overlay")).generate("docs/winter_fashion.jpg");
```

```flutter
cloudinary.image('docs/winter_fashion.jpg').transformation(Transformation()
	.namedTransformation(NamedTransformation.name("dark_text_overlay")));
```

```kotlin
cloudinary.image {
	publicId("docs/winter_fashion.jpg")
	 namedTransformation(NamedTransformation.name("dark_text_overlay")) 
}.generate()
```

```jquery
$.cloudinary.image("docs/winter_fashion.jpg", {transformation: ["dark_text_overlay"]})
```

```react_native
new CloudinaryImage("docs/winter_fashion.jpg").namedTransformation(
  name("dark_text_overlay")
);
```Generates the image tag: `<img src="https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay/docs/winter_fashion.jpg">`

1. Use the generated image tag in your code.
3. To make the image responsive, create named transformations for mobile and tablets, as well and use `srcset` in your HTML structure.
   
    ```html
    <img id="dark_text"
      src="https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay/docs/winter_fashion.jpg"
      srcset="
        src=https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay_mobile/docs/winter_fashion.jpg 400w,
        src=https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay_tablet/docs/winter_fashion.jpg 800w,
        src=https://res.cloudinary.com/demo/image/upload/t_dark_text_overlay/docs/winter_fashion.jpg 1200w"
      sizes="(max-width: 600px) 400px, (max-width: 1024px) 800px, 1200px"
      alt="Hero image">
    ```

## Other delivery channels

Besides delivering non-product images on your website, you can also deliver to the following channels:

* **Social media**: Optimize images for different platform size and format requirements.

* **Third-party stakeholders**: Ensure compliance with background color or file format constraints and protect your assets by watermarking.

* **Email campaigns**: Maintain quality within file size and resolution limitations.

* **Market places**: Adhere to specific format, background, metadata, and naming rules.

For more information, see [Multi-channed content delivery](ecommerce_workflows_delivery_channels).

