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

# Media Optimizer configuration


Cloudinary's Media Optimizer is for targeted Enterprise organizations and simplifies the process to optimize and deliver high-quality media with high performance, low latency and massive scalability. 
> **The Media Optimizer documentation includes:**:
>
> **Guides**

> * [Quick starts](media_optimizer_quickstart)

> * [Configuration](media_optimizer_configuration)

> * [Dashboard](media_optimizer_dashboard)

> * [Reports](media_optimizer_reports)

> * [Transformations](media_optimizer_transformations)
> **References**

> * [Media Optimizer API](media_optimizer_api)

> * [Transformation reference](media_optimizer_transformation_reference)
This page explains how to configure your Media Optimizer setup by introducing you to the [key concepts](#key_concepts), providing some [examples](#configuration_examples) showing what to configure in different situations, and providing step-by-step instructions for each element of the configuration.

## Key concepts

* **Media source**: The location of your high quality media assets. The media source configuration in the console provides details about your media storage locations and how to access them.
* **Optimization profile**: Identifies a set of media assets by their delivery URL, and defines how they are delivered based on the source of the original media and applied transformations. Optimization profiles ultimately bring together all the different configuration components.
* **Mapping function**: Determines media transformations that are already being applied to your media sources through existing delivery platforms. Mapping functions enable Media Optimizer to apply the same transformations when delivering the media from its original source.
* **Domain**: The base part of your Media Optimizer URL. By default this is `https://<cloud_name>.mo.cloudinary.net`, but you can use your own domain by setting up a custom domain.
* **Path prefix**: Set in the optimization profile, the path prefix can be thought of as an extension to the domain, which can be used to categorize your media. This allows you to create more than one optimization profile for the same domain, and treat some media differently to others, as shown in [Example 7](#example_7_using_two_delivery_profiles_and_a_web_address_media_source). The path prefix is included in your Media Optimizer URLs, but it is **not** a folder in your media source.
* **Media Optimizer URL**: (Also known as the **delivery URL**). The URL required to deliver media from your media source through Media Optimizer. It combines the domain and any path prefix set in the optimization profile, with the path to the media in the media source. If you already use a platform that optimizes your media through URL parameters, you can keep these in your Media Optimizer URL and Media Optimizer will map them to Cloudinary transformations.

## Configuration examples

The objective of the Media Optimizer configuration is to start optimizing the delivery of your media with minimal changes to your site. It should allow you to keep the media URLs on your site either completely unchanged, or needing only minor updates. This is achieved by defining media sources and mapping functions that are brought together in an optimization profile, determining how to treat each media URL request.

There are many different ways to configure Media Optimizer, depending on your situation.

* If you are implementing a new website, or already have a website on which you are displaying un-optimized media, then the configurations shown in [Example 1](#example_1_using_the_default_domain_and_a_web_address_media_source), [Example 2](#example_2_using_a_custom_domain_and_a_web_address_media_source), or [Example 3](#example_3_using_the_default_domain_and_an_aws_s3_media_source) will get you started. 
* If you currently store your media in Cloudinary, [Example 4](#example_4_using_the_default_domain_and_a_cloudinary_media_source) shows how to set up a Cloudinary media source, and choose the right mapping function.
* If you want publicly available media to be fetched through Media Optimizer, see [Example 5](#example_5_using_the_default_domain_and_an_http_proxy_media_source).
* If you already have a website up and running, and are using a different platform for optimization, [Example 6](#example_6_mapping_custom_transformations_in_the_original_url) shows how to map those optimizations to [Media Optimizer transformations](media_optimizer_transformations).
* If you want to treat some media differently to others, check out [Example 7](#example_7_using_two_delivery_profiles_and_a_web_address_media_source). 
* If your media is stored in multiple locations, see [Example 8](#example_8_using_the_default_domain_and_multiple_media_sources).

The configuration is very flexible, so you can use a combination of the above examples, and others, to cater for the needs of your site.

The following examples assume a cloud name of `mycloud`.

### Example 1: Using the default domain and a web address media source

This is the most basic example, which is covered by the [Quick start for web address media source](media_optimizer_quickstart_web_address). Whether you have an existing site, or are building a new one, this configuration will get you up and running quickly, though later you may want to take a more nuanced approach, such as in [Example 7](#example_7_using_two_delivery_profiles_and_a_web_address_media_source). 

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://www.mydomain.com/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [Web Address](#web_address)
  * **URI base**: `https://www.mydomain.com`
2. Ensure your [optimization profile](#create_an_optimization_profile) includes:
  * **Media source**: as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: `Media Optimizer` (**Default**)
3. On your site, replace `https://www.mydomain.com` with `https://mycloud.mo.cloudinary.net`.

---

### Example 2: Using a custom domain and a web address media source

This is the same as [Example 1](#example_1_using_the_default_domain_and_a_web_address_media_source), but uses a custom domain instead of the default domain. Use this configuration to serve media from your domain, with no changes to your site.

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://www.mydomain.com/rest/of/the/path.jpg` | `https://www.mydomain.com/rest/of/the/path.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
   * **Type**: [Web Address](#web_address)
   * **URI base**: `https://www.mydomain.com`
2. [Create a custom domain](#create_a_custom_domain). This involves creating a support request to set up the DNS routing required for you to use your own domain.
   * **Domain**: `https://www.mydomain.com`
3. [Create an optimization profile](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://www.mydomain.com`
  * **Mapping function**: `Media Optimizer` (**Default**)

---

### Example 3: Using the default domain and an AWS S3 media source

Similar to [Example 1](#example_1_using_the_default_domain_and_a_web_address_media_source), this is the most basic example, but with media stored in an AWS S3 bucket. This is covered by the [Quick start for AWS S3 media source](media_optimizer_quickstart_aws_s3). In the example shown, `https://www.mydomain.com` is the proxy used to serve media from the S3 bucket, `s3://bucket_name/bucket_folder/rest/of/the/path.jpg`.

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://www.mydomain.com/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [AWS S3](#aws_s3)
  * **Bucket name**: `bucket_name`
  * **Bucket folder**: `bucket_folder`
  * **Access key** and **Secret key**: as appropriate
2. Ensure your [optimization profile](#create_an_optimization_profile) includes:
  * **Media source**: as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: `Media Optimizer` (**Default**)
3. On your site, replace `https://www.mydomain.com` with `https://mycloud.mo.cloudinary.net`.

---

### Example 4: Using the default domain and a Cloudinary media source

In this example, the media source is Cloudinary. As Media Optimizer does not come with Cloudinary storage, this example assumes the user has an existing Cloudinary account (with cloud name `demo`), and perhaps only uses optimization features, so wants to migrate to Media Optimizer, leaving their assets stored in Cloudinary. 

The example shows transformations being applied to resize the image (`c_fill,h_200,w_200`). These transformations are interpreted by the `Programmable Media` mapping function to map to the equivalent transformations in Media Optimizer.  

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://res.cloudinary.com/demo/image/upload/c_fill,h_200,w_200/docs/shoes` | `https://mycloud.mo.cloudinary.net/image/upload/c_fill,h_200,w_200/docs/shoes`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [Cloudinary](#cloudinary)
  * **Storage cloud name**: `demo`  
2. [Create an optimization profile](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: `Programmable Media`
3. On your site, replace `https://res.cloudinary.com/demo` with `https://mycloud.mo.cloudinary.net`.

---

### Example 5: Using the default domain and an HTTP proxy media source

In this example, the media source is a publicly accessible HTTP URL. You can use this configuration for media on your site that you don't own, for example, to fetch social media profile pictures. This is covered by the [Quick start for HTTP proxy media source](media_optimizer_quickstart_http_proxy). 

{table:class=no-borders-equal}Original URL | Media Optimizer URL
---|---
`http://www.mydomain.com/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/http://www.mydomain.com/rest/of/the/path.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [HTTP proxy](#http_proxy)
2. [Create an optimization profile](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: `Media Optimizer` (**Default**)
3. On your site, prefix your URLs with  `https://mycloud.mo.cloudinary.net/`.

---

### Example 6: Mapping custom transformations in the original URL

Similar to [Example 1](#example_1_using_the_default_domain_and_a_web_address_media_source), this example uses the default domain and a web address media source, but URLs can include optimization parameters from a different platform (e.g. `size=small`).

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://www.mydomain.com/rest/of/the/path.jpg?size=small` | `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg?size=small`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [Web Address](#web_address)
  * **URI base**: `https://www.mydomain.com`
2. [Create a mapping function](#create_a_mapping_function):
   * **Mapping function code**: JavaScript code to convert `size=small` to a Cloudinary transformation (see [mapping function code examples](#mapping_function_code_examples))
3. [Create an optimization profile](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: as created
4. On your site, replace `https://www.mydomain.com` with `https://mycloud.mo.cloudinary.net`.

---

### Example 7: Using two optimization profiles and a web address media source

Depending on your site, you may find that you need a hybrid configuration, whereby some of the media on your site can be delivered with low quality settings, saving more bytes, whereas other media needs high quality settings. You can achieve this using more than one optimization profile.

{table:class=no-borders-equal}Original URL | Media Optimizer URL
---|---
`https://www.mydomain.com/rest/of/path/hero.jpg` | `https://mycloud.mo.cloudinary.net/high-quality/rest/of/path/hero.jpg`
`https://www.mydomain.com/rest/of/path/thumb.jpg` | `https://mycloud.mo.cloudinary.net/low-quality/rest/of/path/thumb.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [Web Address](#web_address)
  * **URI base**: `https://www.mydomain.com`
2. [Create a transformation for high quality](media_optimizer_transformations#creating_a_named_transformation):
  * **Quality**: `Auto:Best`
3. [Create a transformation for low quality](media_optimizer_transformations#creating_a_named_transformation):
  * **Quality**: `Auto:Low`
4. [Create an optimization profile for high quality](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://www.mydomain.com`
  * **Path prefix**: `high-quality`
  * **Base transformation**: select the named transformation as created for high quality
  * **Mapping function**: `Media Optimizer` (**Default**)
5. [Create an optimization profile for low quality](#create_an_optimization_profile):
  * **Media source**: as created
  * **Domain**: `https://www.mydomain.com`
  * **Path prefix**: `low-quality`
  * **Base transformation**: select the named transformation as created for low quality
  * **Mapping function**: `Media Optimizer` (**Default**)
6. On your site, replace `https://www.mydomain.com` with one of the following, depending on how you want that asset to be delivered:
  * `https://mycloud.mo.cloudinary.net/high-quality`
  * `https://mycloud.mo.cloudinary.net/low-quality` 

---

### Example 8: Using the default domain and multiple media sources

Similar to [Example 1](#example_1_using_the_default_domain_and_a_web_address_media_source), this example uses the default domain and a web address media source, plus another media source, an AWS S3 bucket. The order in which you specify the media sources in the optimization profile is important, so if you have files of the same name in both sources, the first file found is used.

In the example shown, `https://www.mydomain.com` is the proxy used to serve media from the S3 bucket, `s3://bucket_name/bucket_folder/rest/of/the/path.jpg`.

{table:class=no-borders}Original URL | Media Optimizer URL
---|---
`https://www.webdomain.com/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`
`https://www.mydomain.com/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

**Required action**: 

1. [Connect a media source](#connect_a_media_source):
  * **Type**: [Web Address](#web_address)
  * **URI base**: `https://www.webdomain.com`
1. [Create a second media source](#connect_a_media_source):
  * **Type**: [AWS S3](#aws_s3)
  * **Bucket name**: `bucket_name`
  * **Bucket folder**: `bucket_folder`
  * **Access key** and **Secret key**: as appropriate
1. Ensure your [optimization profile](#create_an_optimization_profile) includes:
  * **Media sources**: add both media sources, as created
  * **Domain**: `https://mycloud.mo.cloudinary.net` (**Default**)
  * **Mapping function**: `Media Optimizer` (**Default**)
1. On your site, replace `https://www.webdomain.com` and `https://www.mydomain.com` with `https://mycloud.mo.cloudinary.net`.

## Initial setup

Before you can configure Media Optimizer, you need to set your domain and operating region. If not yet set, a dialog appears when you try to create a new configuration entity, such as an optimization profile or media source.

![Initial setup dialog](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/initial_setup_dialog.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")

* **Domain identifier**: Also known as your cloud name, this is used in your media delivery URLs.  You can either change it or leave it as the one you were given at sign up. You can change this at a later date in your Console Settings, but once you start using your configuration, it is best not to change it.
  * For a domain identifier of **mycloud**, the Media Optimizer URL domain is: `https://mycloud.mo.cloudinary.net`
* **Operating region**: Select the location that is closest to your existing media storage and/or the majority of your users. This helps to fetch and deliver your media in the most efficient way. Once set, this cannot be changed.

> **NOTE**: To use a custom domain, see [Create a custom domain](#create_a_custom_domain).

## Connect a media source

**Media source** configurations provide details about your media storage locations and how to access them. You can connect to more than one media source if you store your media assets in multiple locations, and you can reference your media sources in one or multiple [optimization profiles](#create_an_optimization_profile).

![Media sources](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/media_sources.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")

To connect to a **media source**:

1. In the Media Optimizer console, navigate to **Configuration > Media Sources** and click **Add New**.
2. Complete the form:
   * **Media source name**: Enter a name for your media source configuration.
   * **Type**: Select where your media is stored. You can choose from:
     * [Web Address](#web_address)
     * [HTTP Proxy](#http_proxy)
     * [AWS S3](#aws_s3)  
     * [Google Storage](#google_storage)
     * [Cloudinary](#cloudinary)
   * Enter details about your media source based on the type.
3. Click **Save**.

### Types of media sources

Media Optimizer supports a number of types of media sources, as described in the following sections.

> **NOTE**: If your media storage is not covered by any of the types listed, please [contact support](https://support.cloudinary.com/hc/en-us/requests/new).

#### Web address

Use the **Web Address** type when your media is stored on an HTTP accessible web server (most likely owned and maintained by yourself).

For an asset stored at:

`http://www.mydomain.com/rest/of/the/path.jpg`

by default, the Media Optimizer delivery URL takes the form:

`https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

##### Web address settings

{table:class=reference-two-col}Setting | Description
---|---
URI base | The full URL of the web server (including http:// or https://).
Headers | Advanced option for specifying headers in key/value pairs to include in the fetch request, for authentication or authorization purposes. Example:**Key**: `Authorization`**Value**: `Bearer {{vars.token}}``{{vars.token}}` is an example of an interpolated variable, defined in the [mapping function code](#mapping_function_code). 
URI template | Advanced option for specifying parameters to include in the fetch request. You can use interpolated variables that are defined in the [mapping function code](#mapping_function_code). For an example, see [URI template](#uri_template).

---

#### HTTP proxy

Use the **HTTP proxy** type to fetch media from a publicly accessible HTTP URL. 

For an asset stored at:

`http://www.mydomain.com/rest/of/the/path.jpg`

by default, the Media Optimizer delivery URL takes the form:

`https://mycloud.mo.cloudinary.net/http://www.mydomain.com/rest/of/the/path.jpg`

##### HTTP proxy settings

There are no settings associated with the HTTP proxy type.

---

#### AWS S3

Use the **AWS S3** type to fetch your media from an AWS S3 storage bucket.

For an asset stored at:

`s3://<bucket_name>/<bucket_folder>/rest/of/the/path.jpg`

by default, the Media Optimizer delivery URL takes the form:

`https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

##### AWS S3 settings

{table:class=reference-two-col}Setting | Description
---|---
Bucket name | The name of the S3 bucket.
Bucket folder | The bucket folder containing your media files.**Note:** Bucket folder names containing spaces are currently not supported by Media Optimizer. 
Access key | The **access key ID** required to read from your S3 bucket.
Secret key | The **secret access key** required to read from your S3 bucket.
URI template | Advanced option for specifying parameters to include in the fetch request. You can use interpolated variables that are defined in the [mapping function code](#mapping_function_code). For an example, see [URI template](#uri_template).

 

##### AWS S3 security

**Read-only** permissions are required to access your storage. This can be achieved in one of two ways:

* Either, [using keys](#aws_s3_using_keys)
* Or, [allowlisting your S3 bucket](#aws_s3_allowlisting)

###### **Using keys to access your S3 bucket:**

1. Enter the **access key ID** for your S3 bucket in the **Access key** field of the [AWS S3 settings](#aws_s3_settings).
2. Enter the **secret access key** for your S3 bucket in the **Secret key** field of the [AWS S3 settings](#aws_s3_settings).

###### **Allowlisting your S3 bucket:**

1. Provide Cloudinary permission to **read** your protected content. Once set, these permissions should remain in place throughout the entire time that the media source is in use:
  1. In [Amazon's AWS S3 Console](https://console.aws.amazon.com/s3/home), select the relevant bucket.
  2. In the Bucket Policy properties, paste the following policy text. 
    Keep the `Version` value as shown below, but change `BUCKETNAME` to the name of your bucket. If a policy already exists, append this text to the existing policy:

        ```json
        {
          "Version": "2012-10-17",
          "Id": "AWSConsole-AccessLogs-Policy-BUCKETNAME-cloudinary",
          "Statement": [
            {
              "Sid": "AWSConsoleStmt-BUCKETNAME-cloudinary",
              "Effect": "Allow",
              "Principal": {
                "AWS": "232482882421"
              },
              "Action": [
                  "s3:GetObject"
              ],
              "Resource": "arn:aws:s3:::BUCKETNAME/*"
            }
          ]
        }
        ```
2. Add an empty file to your bucket, with your cloud name as the filename, using this structure:
  `.wellknown/cloudinary/<your_cloud_name>` On creation of the media source, Cloudinary verifies the file and remembers that this bucket is allowlisted for the cloud in which the media source is configured. Therefore, the file needs to be in place before the media source is created, and can be deleted after it is created.

    
 -->
---

#### Google storage

Use the **Google Storage** type to fetch your media from a Google storage bucket.

For an asset stored at:

`gs://<bucket_name>/<bucket_folder>/rest/of/the/path.jpg`

by default, the Media Optimizer delivery URL takes the form:

`https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg`

##### Google storage settings

{table:class=reference-two-col}Setting | Description
---|---
Bucket name | The name of the Google Storage bucket.
Bucket folder | The bucket folder containing your media files.
Service account key | The JSON file downloaded from the **Keys** tab in your service account (see [Creating service account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating) in Google's documentation). 
URI template | Advanced option for specifying parameters to include in the fetch request. You can use interpolated variables that are defined in the [mapping function code](#mapping_function_code). For an example, see [URI template](#uri_template).

##### Google storage security

**Read-only** permissions are required to access your storage. This can be achieved in one of two ways:

* Either, [using a service account key](#gs_using_keys)
* Or, [allowlisting your Google storage bucket](#gs_allowlisting)

###### **Using a service account key:**

1. Create a service account and bucket read role for Cloudinary.
2. Download the JSON key file from the **Keys** tab in your service account.
3. Upload the JSON key file in the **Service account key** field of the [Google storage settings](#google_storage_settings).

###### **Allowlisting your Google storage bucket:**

1. Provide Cloudinary permission to **read** your protected content. Once set, these permissions should remain in place throughout the entire time that the media source is in use:
  1. In your [Google Cloud Platform console](https://console.cloud.google.com), go to your Google bucket's main page.
  2. Select to edit bucket permissions. 
  3. Add `service@cloudinary-gcs-production.iam.gserviceaccount.com` as a member and give it the **Storage Object Viewer** role.
2. Add an empty file to your bucket, with your cloud name as the filename, using this structure:
  `.wellknown/cloudinary/<your_cloud_name>` On creation of the media source, Cloudinary verifies the file and remembers that this bucket is allowlisted for the cloud in which the media source is configured. Therefore, the file needs to be in place before the media source is created, and can be deleted after it is created.
 -->

 ---

#### Cloudinary

If your media is stored in a Cloudinary product environment that has a Media Library, your Media Optimizer product environment must be part of the same overall account to use this option (each will have different cloud names). If the two product environments are not part of the same overall account you can use the [Web address](#web_address) type instead.

If using Cloudinary purely for storage, and not transformations, you can use the **Media Optimizer** mapping function. Otherwise you should use the **Programmable Media** mapping function. The Media Optimizer URL depends on the mapping function used:

Media Type | Path to Original Media | Media Optimizer URL
---|---|---
Image | `https://res.cloudinary.com/demo/image/upload/``rest/of/the/path` | With **Programmable Media** mapping function:`https://mycloud.mo.cloudinary.net/image/upload/``rest/of/the/path`With **Media Optimizer** mapping function:`https://mycloud.mo.cloudinary.net/``rest/of/the/path`
Video | `https://res.cloudinary.com/demo/video/upload/``rest/of/the/path` | With **Programmable Media** mapping function:`https://mycloud.mo.cloudinary.net/video/upload/``rest/of/the/path`With **Media Optimizer** mapping function:`https://mycloud.mo.cloudinary.net/``rest/of/the/path` + extension

> **NOTE**:
>
> The **Programmable Media** mapping function handles only Media Optimizer [supported transformations](media_optimizer_transformations#supported_transformations). To use other Programmable Media transformations, use the [Web address](#web_address) media source type together with the **Media Optimizer** mapping function.

##### Cloudinary Console Settings

{table:class=reference-two-col}Setting | Description
---|---
Storage cloud name | The cloud name of the Cloudinary product environment where your media is stored. It must share the same overall Cloudinary account as the Media Optimizer product environment.

## Create a mapping function

**Mapping functions** are used to identify media transformations that are already being applied to your media sources through existing delivery platforms. They enable Media Optimizer to apply the same transformations when delivering the media from its original source.

![Mapping functions](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/mapping_functions.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")
Media Optimizer provides two built-in mapping functions that allow you to specify [Media Optimizer transformations](media_optimizer_transformations#supported_transformations) as part of the delivery URL (applied in addition to those defined in the optimization profile):

* **Media Optimizer**: This mapping function caters for 
  * Transformation parameters added as a query string to the delivery URL, for example: `https://mycloud.mo.cloudinary.net/rest/of/the/path.jpg?tx=c_fit,h_500,w_500` 
  * The resource type specified as a query string, overriding any determining of `resource_type` in the mapping function due to the extension given. This is particularly useful if no extension is given, for example:`https://mycloud.mo.cloudinary.net/rest/of/the/path?resource_type=image`where `resource_type` can be set to `image`, `video` or `raw`. 
* **Programmable Media**: This mapping function caters for transformation parameters within a URL, as they would be if your media source was **Cloudinary**, for example: `https://mycloud.mo.cloudinary.net/image/upload/c_fit,h_500,w_500/v1/sample.jpg`

> **NOTE**: You cannot edit or delete these built-in mapping functions.
      
You can provide your own custom mapping function to cater for any non-Cloudinary transformations. 

To create a **mapping function**:

1. Navigate to **Configuration > Mapping Functions** and click **Add New**.
2. Complete the form:
   * **Mapping function name**: Enter a name for the mapping function.
   * **Mapping function code**: Enter here a JavaScript function. For details, see [Mapping function code](#mapping_function_code).
3. Click **Save**.

### Mapping function code

Mapping functions require JavaScript code to analyze incoming media URLs, extract transformations and determine the path to the highest quality original media.

As mapping functions are an advanced concept, our [support team](https://support.cloudinary.com/hc/en-us/requests/new) are on hand to help you create any that you need. 

#### Signature

The expected signature of the function is:

```js
function map(request, environment) {
  ...
}
```

The `request` parameter is an object that represents the delivery URL and the context in which it was requested. It contains the following attributes:

{table:class=med-1stcol}Attribute | Description | Example
---|---|---
`url` | The full delivery URL. | `https://myhost.com/a/b/c.jpg?v=1&p=2`
`path` | The asset path part of the `url`. | `/a/b/c.jpg`
`query` | A hash of `string => string[]` representing the query part of  the `url`. | `{"v" => ["1"], "p" => ["2"]}`

The `environment` parameter is an object that represents the delivery URL context for the invocation. It contains the following attributes:

{table:class=wide-lastcol}Attribute | Description
---|---
`defaultTransformation` | The transformation defined in the optimization profile.
`pathPrefix` | The path prefix identified for this specific request, as defined in the optimization profile.
`timeMs` | The current time in milliseconds.
`options` | A hash of `string => string` that represents the mapping function options.

#### Outputs

The output is a hash of `string => string` with the following keys:

{table:class=wide-lastcol}Key | Description | Example
---|---|---
`media_key` | A globally unique identifier for the media within Cloudinary's storage and cache. | `a/b/c.jpg`
`fwd_key` | Optional. An identifier for the media within a media source. By default, `fwd_key` and `media_key` are identical, but they could be different if, for example you wanted to map two different sources to the same Cloudinary cache entry. | `a/b/c.jpg`
`transformation` | The Cloudinary transformation. | `c_fit,h_100,w_150`
`resource_type` | The type of resource. | `image`, `video` or `raw`
`media_source_template_variables` | A hash of `string => string` that may be used by the media source **URI template** field and other advanced media source fields. | `{"timestamp": "1612733077", "signature": "1234"}`

#### Mapping function code examples

The following code samples show simple examples of mapping functions, to demonstrate their structure, parameters and logic that may be used. 

##### Example 1

In this example, the request URL contains query parameters that control the dimensions of the delivered image. The code maps these query parameters to Cloudinary [transformation parameters](media_optimizer_transformations#supported_transformations). Media Optimizer then adds these transformations to the default (base) transformation that's specified in the [optimization profile](#create_an_optimization_profile).

It also removes any path prefix found in the path, as this is not required in the request to be sent to the origin. This enables `{{fwd_key}}` to be used in the [URI template](#uri_template) field of the media source to fetch the media. 

![URI template field](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/URI_template.png?tx=c_scale,w_400/dpr_2.0 "width: 400, popup: true")

```js
function map(request, environment) {
  let transformation = environment.defaultTransformation + '/';

  // If the query parameters include width and height, map them to Cloudinary transformations
  if (request.query.width && request.query.height) {
    transformation += `c_limit,h_${request.query.height},w_${request.query.width}/`;
  } 
  // Otherwise if a size is specified in the query parameters, map it to a specific transformation
  else if (request.query.size) {
    switch(request.query.size) {
      case 'small':
        transformation += "c_fit,h_100,w_150/";
        break;
      case 'medium':
        transformation += "c_fit,h_240,w_360/";
        break;
      case 'large':
        transformation += "c_fit,h_480,w_720/";
        break;
    }
  }
  let path = request.path;

  // Remove the path prefix from the path
  if (environment.pathPrefix.length > 0) {
      path = path.slice(`/${environment.pathPrefix}/`.length);
  }

  return {
    fwd_key: path,
    media_key: request.path,
    transformation,
    resource_type: 'image',
  };
}
```

Given this request and configuration settings:

* Request URL: `https://mycloud.mo.cloudinary.net/images/footwear/shoes.jpg?size=small`
* Path prefix: `images`
* Base transformation: `t_auto_format_auto_quality`

the mapping function would provide the following output variables:

* `fwd_key`: **/footwear/shoes.jpg**
* `media_key`: **/images/footwear/shoes.jpg**
* `transformation`: **t_auto_format_auto_quality/c_fit,h_100,w_150/**
* `resource_type`: **image**

##### Example 2

In this example, the request URL contains query parameters that control the width of the delivered image, either as a width in pixels (e.g. `filter=w407` that gets mapped to `w_407`) or as a decimal string (e.g. `filter=ds2` that gets mapped to `w_0.2`). 

In addition to returning the respective Cloudinary transformation, the host is returned in `media_source_template_variables`, so that it can be used in the **Headers** setting of a [Web address](#web_address) media source (**Key**: `X-Forwarded-Host`, **Value**: `{{vars.x-forwarded-host}}`). 

![Headers fields](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/headers.png?tx=c_scale,w_400/dpr_2.0 "width: 400, popup: true")

```js
function map(req, env) {

  // Check for the 'filter' query parameter and map it to a Cloudinary transformation
  var params = '';
  if ('filter' in req.query){
    filter = req.query['filter'];
    params = filter.split(',').map(s=> s.match(/[a-zA-Z]+|[0-9]+/g)).map(item => (item[0] == 'ds')? 'w_0.' + item[1]:item[0] + '_' + item[1]).join(',');
    params+='/';
  }

  // Get the hostname from the request URL
  const new_url = String(req.url);
  const regex = /https?:\/\/([^\/]+).*/g;
  const found = regex.exec(new_url);
  const hostname = found[1];

  return {
      media_key: req.path,
      transformation: params + "f_auto/q_auto",
      fwd_key: req.path,
      resource_type: "image",
      media_source_template_variables: {"x-forwarded-host": hostname}
  };
}
```

Given this request:

* Request URL: `https://mycloud.mo.cloudinary.net/footwear/shoes.jpg?filter=w407`

the mapping function would provide the following output variables:

* `media_key`: **/footwear/shoes.jpg**
* `transformation`: **w_407/f_auto/q_auto**
* `fwd_key`: **/footwear/shoes.jpg**
* `resource_type`: **image**
* `vars.x-forwarded-host`: **mycloud.mo.cloudinary.net**

#### URI template

Variables defined in your mapping function can be used in the **URI template** field and other advanced media source fields in your media source definition. 

Variables defined in `media_source_template_variables` in the mapping function, are referenced using `vars` in the media source fields.

For example:

`{{fwd_key}}?hst={{vars.x-forwarded-host}}`

## Create a custom domain

If you are on a paid plan and have your own domain name that you want to use instead of Media Optimizer's default domain (`https://<cloud_name>.mo.cloudinary.net`), you can create a custom domain. 

![Domains](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/custom-domain-ui.png?tx=c_scale,w_499/dpr_2.0 "width: 499, popup: true")

To create a custom domain:

1. Navigate to **Configuration > Domains** and click the **contact support** link.
2. Complete the support request form, specifying the name of the domain you want to use.

The support team will add the domain to your configuration and set up the required DNS routing.

## Create an optimization profile

**Optimization profiles** identify a set of media assets by their delivery URL, and define how they are delivered based on the source of the original media and defined transformations. Each optimization profile brings together one or more [media sources](#connect_a_media_source), a [mapping function](#create_a_mapping_function), a [domain](#create_a_custom_domain) and a [transformation](media_optimizer_transformations#creating_a_named_transformation).

![Optimization profiles](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/optimization_profiles.png?tx=c_scale,w_500,dpr_2.0 "width: 500, popup: true")

To create an **optimization profile**:

1. Navigate to **Configuration > Optimization Profiles** and click **Add New**.
2. Complete the form:
   * **Optimization profile name**: Enter a name for the optimization profile.
   * **Media sources**: If you've already configured media sources in Media Optimizer, select the relevant ones from the drop-down list. Otherwise, you can click **Connect a new media source** to open a dialog similar to the [Media sources configuration](#connect_a_media_source) dialog and create a new configuration, which you can select on completion of the dialog. When more than one media source is selected, the order in which they are specified is important. Media Optimizer tries to fetch the asset from the first media source, and if it is not found, it moves onto the next media source. Once found, it does not continue to the next media source.
   * **Optimization profile URL**: Set the domain and path prefix to define the base URL that identifies media belonging to the optimization profile.
   * **Base transformation**: Select the [transformation](media_optimizer_transformations#creating_a_named_transformation) to apply to all media in the profile. The transformation is ignored for any raw files belonging to this optimization profile. 
   * **Mapping function**: In the advanced settings, select the [mapping function](#create_a_mapping_function) that should be used to extract transformations.
3. Click **Save**.

## Enable an optimization profile

After creating an optimization profile, you need to enable it to start optimizing your media delivery through it. 

To enable an optimization profile:

1. Navigate to **Configuration > Optimization Profiles**.
2. Select the optimization profile to enable.
3. Select **Enable optimization profile** from its kebab menu.

![Enable optimization profile](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/enable_optimization_profile.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")

## Test your setup

To test your setup, choose a Media Optimizer URL for a media file that you want to deliver through your site. The structure of your Media Optimizer URLs depends on your setup - you can see some examples in [Configuration examples](#configuration_examples). 

Enter the URL into a browser and check that it returns an image or a video.

If you get an error, ensure you have one or more optimization profile [enabled](#enable_an_optimization_profile). You can also check out [troubleshooting](#troubleshooting).

## Inspect and replace media URLs

You can inspect media URLs on your site using browser tools. For example, in Chrome:

1. Right-click an image and select **Inspect**.
1. In the panel that appears, click **Network**.
1. Select the **Filter** icon and click **Img**.
1. Reload the page, and see the images being requested.
1. Hover over an image name to see the full URL, including the domain:
   ![Inspect media URLs](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/inspect_media_urls.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")
1. Click the name to see the details:
   ![See details of a media URL request](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/inspect_media_url_details.png?tx=c_scale,w_700/dpr_2.0 "width: 700, popup: true")
   If the image is being delivered through Media Optimizer, you'll see the Media Optimizer domain in the Request URL, the content type most likely being different from your original if you have automatic format enabled, and the image served through Cloudinary. 

If the image is not being served through Cloudinary, be sure to update the media URLs in your source code.

For example, if your cloud name is `mycloud`, given the path to the original media, you can see what the new delivery URL would be:
Media Source | Path to Original Media | Media Optimizer URL
---|---|---
Web Address | `http://www.mydomain.com/``rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/``rest/of/the/path.jpg`
HTTP Proxy | `http://www.mydomain.com/``rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/``http://www.mydomain.com/rest/of/the/path.jpg`
AWS S3 | `s3://bucket_name/bucket_folder/``rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/``rest/of/the/path.jpg`
Google Storage |`gs://bucket_name/bucket_folder``/rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/``rest/of/the/path.jpg`
Cloudinary | `https://res.cloudinary.com/demo/image/upload/``rest/of/the/path.jpg` | `https://mycloud.mo.cloudinary.net/``rest/of/the/path.jpg`Note: This structure can vary - [learn more](media_optimizer_configuration#cloudinary). 

## Using Media Optimizer with external platforms

Many websites these days are maintained via content management systems or e-commerce platforms, which store media as part of their functionality. The exact steps for using Media Optimizer with these platforms depend on your specific platform, configurations, customizations, plugins, and more. This section provides some general guidance and examples on using Media Optimizer with these kinds of external platforms.

The main process is to find out the base URL that the platform uses to store media, and to use this as your Media Optimizer media source (configured as a [Web Address type](#web_address)). Then, find a way to replace the base URL that the platform uses for media URLs with your Media Optimizer domain.

Some platforms may require manually replacing delivery URLs. Other platforms may have built-in options or plugins that you can use to automate these changes. For some platforms you may need to customize the underlying code.

### Platform examples

> **INFO**: Ultimately, how you integrate your external platform with Media Optimizer depends on your platform setup, plugins or customizations that you may have configured, so you should tailor your solution to your particular circumstance. 

The examples given here only show possible methods of integration and may not work exactly as described for your  specific setup.

* [Contentful](https://www.contentful.com/): 
  1. Connect a Web Address media source with: **URI base**: `https://images.ctfassets.net/<your_space_id>`
  1. Manually replace `https://images.ctfassets.net/<your_space_id>` in all your media URLs, with your Media Optimizer domain, `https://<cloud_name>.mo.cloudinary.net`. 

* [Magento](https://business.adobe.com/products/magento/magento-commerce.html): 
  1. Connect a Web Address media source with: **URI base**: `https://<your_magento_domain>/media`
  1. Use Magento's built-in functionality for [Using a Content Delivery Network](https://docs.magento.com/user-guide/system/media-storage-content-delivery-network.html).  Set **Base URL for User Media Files** and **Secure Base URL for User Media Files** to `https://<cloud_name>.mo.cloudinary.net` to replace `https://<your_magento_domain>/media`.

* [Shopify](https://www.shopify.com/):
  1. Connect a Web Address media source with: **URI base**: `https://cdn.shopify.com`
  1. Customize the underlying code to replace the base URL part of the media URL with the Media Optimizer domain. For example, replacing `cdn.shopify.com` with `<cloud_name>.mo.cloudinary.net`:
  
        ```
        img src="{{ img_url | replace:'cdn.shopify.com', 'yourcloud.mo.cloudinary.net' }}"
        ```

* [WordPress](https://wordpress.org/):
  1. Connect a Web Address media source with: **URI base**: `https://<your_wp_domain>`
  1. Use WordPress's [CDN Enabler](https://wordpress.org/plugins/cdn-enabler/) plugin to rewrite your media URLs. Set **CDN Hostname** to `https://<cloud_name>.mo.cloudinary.net` to replace `https://<your_wp_domain>`. You may also want to edit the **CDN Inclusions** and **CDN Exclusions** lists to include only media file extensions.

## Troubleshooting

When testing Media Optimizer URLs you may encounter errors. There could be many reasons for these errors, including (but not limited to) an incorrect configuration, an incorrect path used to the source media, incorrect credentials used to access a media storage bucket (e.g. AWS S3 or Google Storage), an issue with the mapping function or a missing media asset. 

You can see information about a particular error in the `X-Cld-Error` header field of the HTTP response.

For example, if your browser shows `HTTP ERROR 404`, then using browser tools, you can see that the message in the `X-Cld-Error` field is **Resource not found**:

![Browser tools showing HTTP error](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/resource_not_found.png?tx=c_scale,w_700/dpr_2.0 "width: 700, popup: true")

If, after looking at the error message, you still cannot resolve the issue, our [support team](https://support.cloudinary.com/hc/en-us/requests/new) will be happy to help.

## Invalidate cached assets

If a media asset is already stored on the cache, it is not fetched from its source, so if you change the original asset, you need to clear the cache in order to fetch the correct version of the asset. This is also the case if you [change a named transformation](media_optimizer_transformations#editing_a_named_transformation) that has been applied to a delivered asset. 

To clear the cache for specific media assets, and all media derived from those assets:

1. In the Media Optimizer console, navigate to **Configuration**.
1. Select **Invalidate Cache** from the **Quick Actions** section of the left panel.
  ![Invalidate cache button](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/mo_side_bar.png?tx=c_scale,w_150/dpr_2.0 "width: 150, popup: true")
1. In the URLs text box, enter up to 20 asset URLs to invalidate, separated by new lines.
  ![Invalidate cache dialog](https://demo-mo-docs.mo.cloudinary.net/cld-docs-assets/assets/images/invalidate_cache_dialog.png?tx=c_scale,w_500/dpr_2.0 "width: 500, popup: true")
1. Click **Invalidate Cache**.

> **NOTES**:
>
> * You can also use the [Media Optimizer API](media_optimizer_api#cache_invalidation) to invalidate cache.

> * If you're using Cloudinary as your media source, and replace an asset in your media library, you still have to invalidate the cache in this way. The invalidation discussed in [Invalidating cached media assets on the CDN](invalidate_cached_media_assets_on_the_cdn) does not clear cache used in Media Optimizer.
