A Custom View configuration file defines the necessary requirements to develop and build your application. The configuration of a Custom View is typically defined in a JSON file `custom-view-config.mjs` in the root of your project directory (next to `package.json`). # Supported file extensions The configuration file can be defined in different syntax formats, but it is expected that the file is named `custom-view-config`. The following file extensions can be used: `.json`, `.js`, `.cjs`, `.mjs`, `.ts`. For example: ```js title="custom-view-config.mjs" /** * @type {import('@commercetools-frontend/application-config').ConfigOptionsForCustomView} */ const config = { name: 'Test custom view', // ... }; module.exports = config; ``` # Editor support To facilitate the usage of the Custom View config, you should instruct your editor to provide hints and code completion (IntelliSense) depending on the format of the configuration file. ## Use JSDoc @type expression For non-JSON files, you can annotate the configuration object with a JSDOc `@type` tag, pointing it to the exported TypeScript declaration of the `@commercetools-frontend/application-config` package. ```js title="custom-view-config.js" /** * @type {import('@commercetools-frontend/application-config').ConfigOptionsForCustomView} */ const config = { // ... }; module.exports = config; ``` For TypeScript files `.ts`, you can import the type directly instead. ```ts title="custom-view-config.ts" import type { ConfigOptionsForCustomView } from '@commercetools-frontend/application-config'; const config: ConfigOptionsForCustomView = { // ... }; export default config; ``` # Configuration properties To learn more about the Custom View config properties, read the following. ## `name` The name of the Custom View. It will be used in the Merchant Center when a user is presented with a list of Custom Views available for a specific view. ```js title="custom-view-config.mjs" const config = { name: 'Channels app', // ... }; ``` ## `description` An optional description of the Custom View, for information purposes. ```js title="custom-view-config.mjs" const config = { description: 'Manage Channels', // ... }; ``` ## `cloudIdentifier` The [identifier of the cloud Region](https://docs.commercetools.com/merchant-center-customizations/concepts/merchant-center-api#cloud-identifiers) that the Custom View uses to connect to commercetools API platform. The values map to the actual Merchant Center API URL for that Region. ```js title="custom-view-config.mjs" const config = { cloudIdentifier: 'gcp-eu', // ... }; ``` If a cloud Region is not listed in the values above, you can override the value by adding a `mcApiUrl` property to the Custom View config file with the full origin URL. ## `mcApiUrl` The origin URL of the [Merchant Center API](https://docs.commercetools.com/merchant-center-customizations/concepts/merchant-center-api#hostnames). The value takes precedence over the `cloudIdentifier`. Use this only if the `cloudIdentifier` does not contain a value for the environment you want to connect to. ## `env` An object holding environment specific configurations, for example `development` or `production`. Which environment is used depends on the environment variable `MC_APP_ENV`. If `MC_APP_ENV` isn't set, `NODE_ENV` will be used. If neither is set, it defaults to `development`. The `MC_APP_ENV` is useful if you want to run the production build of the Custom View locally. In this case the `NODE_ENV` needs to be set to `production`. However, because the application runs locally, you need to have the URL references pointing to localhost, thus the `MC_APP_ENV` needs to be set to `development`. ## `env.development.initialProjectKey` A `projectKey` of a commercetools Project you have access to. To be used as the default Project upon login in development. ```js title="custom-view-config.mjs" const config = { env: { development: { initialProjectKey: 'my-project-key', }, }, // ... }; ``` ## `env.development.teamId` Local development is allowed for users belonging to the `Administrators` Team of your Organization with no additional configuration required. If you need to apply more granular permissions for local development of a Custom View, specify the `teamId` of the user's team. For more information, see [Granular permissions for local development](https://docs.commercetools.com/merchant-center-customizations/troubleshooting#granular-permissions-for-local-development-1). ## `env.development.hostUriPath` The [Custom View context](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/commercetools-frontend-application-shell-connectors#hosturl) contains the [`hostUrl`](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/commercetools-frontend-application-shell-connectors#hosturl) property with the value of the built-in application's current URL. When working locally it is set to `http://localhost:3001//@@custom-view-host@@` by default. To simulate your Custom View as if it's rendered within a specific built-in application, you can override the default behavior to provide a custom URI path by setting the `env.development.hostUriPath`. ```js title="custom-view-config.mjs" const config = { env: { development: { hostUriPath: '//products/111-2222-33333-44444', }, }, // ... }; ``` ## `env.production.customViewId` The Custom View ID is provided when you add a Custom View in the Merchant Center (Organizations > Custom Views > Configure > Add). For more information, see [Managing Custom Views in the Merchant Center](https://docs.commercetools.com/merchant-center-customizations/merchant-center/managing-custom-views). ```js title="custom-view-config.mjs" const config = { env: { production: { customViewId: 'ckvtahxl90097sys6har1e6n3', }, }, // ... }; ``` As long as you are developing the Custom View locally, you can define any random value as it's a required field. ## `env.production.url` The full URL value where the Custom View is hosted at. The Merchant Center serves Custom Views on its own domain, but requests are internally forwarded to this URL. For more information, see [Merchant Center Proxy Router](https://docs.commercetools.com/merchant-center-customizations/concepts/merchant-center-proxy-router). ```js title="custom-view-config.mjs" const config = { env: { production: { url: 'https://channels.app', }, }, // ... }; ``` This value is also used to configure the [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) HTTP headers to allow the browser to request data from the application domain. ## `env.production.cdnUrl` The full URL value where the Custom View [static assets](https://docs.commercetools.com/merchant-center-customizations/development/going-to-production#about-static-assets) are hosted, for example when using an external CDN. ```js title="custom-view-config.mjs" const config = { env: { production: { cdnUrl: 'https://cdn.channels.app', }, }, // ... }; ``` If the static assets are hosted alongside the Custom View, you can omit this option and the Custom View `env.production.url` value will be used instead. ## `additionalEnv` An optional object that should be used to inject properties used within your Custom View. These properties are then made available to the [runtime application environment](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/custom-view-config#runtime-application-environment). For example, if the Custom View should reference an external API, or have links to certain support pages: ```js title="custom-view-config.mjs" const config = { additionalEnv: { trackingSentry: 'https://000@sentry.io/000', channelsSupportUrl: 'https://support.channels.app', }, // ... }; ``` ## `oAuthScopes` This field defines the [OAuth scopes and user permissions](https://docs.commercetools.com/merchant-center-customizations/concepts/oauth-scopes-and-user-permissions) required by your Custom View. The configuration is primarily used for local development and does not require prior application registration. For production deployments, use the Merchant Center UI to configure permissions, or use the [`config:sync`](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/cli#configsync) command to synchronize the Merchant Center configuration for your deployed Custom View from this file. You can have "view-only" or "manage-only" OAuth Scopes and leave the other list field empty, as long as at least one OAuth Scope is specified. Alternatively, if at least one additional permission group is configured in [additionalOAuthScopes](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/custom-view-config#additionaloauthscopes), both "view-only" or "manage-only" OAuth Scopes list fields can be left empty. ## `oAuthScopes.view` A list of "view-only" [OAuth Scopes](https://docs.commercetools.com/merchant-center-customizations/api/scopes) required by the Custom View and associated with the `View` permission. ```js title="custom-view-config.mjs" const config = { oAuthScopes: { view: ['view_states'], }, // ... }; ``` ## `oAuthScopes.manage` A list of "manage-only" [OAuth Scopes](https://docs.commercetools.com/merchant-center-customizations/api/scopes) required by the Custom View and associated with the `Manage` permission. ```js title="custom-view-config.mjs" const config = { oAuthScopes: { manage: ['manage_orders'], }, // ... }; ``` Using `manage_` OAuth Scopes always imply the corresponding `view_` OAuth Scope. ## `additionalOAuthScopes` The optional configuration for defining more granular [OAuth Scopes and user permissions](https://docs.commercetools.com/merchant-center-customizations/concepts/oauth-scopes-and-user-permissions#permission-groups). ## `additionalOAuthScopes.*.name` A unique name for the additional permission group. ```js title="custom-view-config.mjs" const config = { additionalOAuthScopes: [ { name: 'movies', }, ], // ... }; ``` The name value must adhere to the following restrictions: - Only lowercase alphabetic characters are allowed. - Must be between 2 and 64 characters. - Hyphens are allowed except as leading, trailing, and adjacent characters. ## `additionalOAuthScopes.*.view` A list of "view-only" [OAuth Scopes](https://docs.commercetools.com/merchant-center-customizations/api/scopes) required by the Custom View and associated with the `View` permission. ```js title="custom-view-config.mjs" const config = { additionalOAuthScopes: [ { name: 'movies', view: ['view_products'], manage: [], }, { name: 'merch', view: ['view_categories'], manage: [], }, ], // ... }; ``` ## `additionalOAuthScopes.*.manage` A list of "manage-only" [OAuth Scopes](https://docs.commercetools.com/merchant-center-customizations/api/scopes) required by the Custom View and associated with the `Manage` permission. ```js title="custom-view-config.mjs" const config = { additionalOAuthScopes: [ { name: 'movies', view: [], manage: ['manage_products'], }, { name: 'merch', view: [], manage: ['manage_categories'], }, ], // ... }; ``` ## `headers` An optional object to configure HTTP headers used by the Custom View. ## `headers.csp` An optional object to extend the default [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) directives. The following directives are allowed to be used: - `connect-src` - `font-src` - `frame-src` - `img-src` - `media-src` - `script-src` - `style-src` You can specify various [CSP source values](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#host-source) (including wildcards `*`) to control from where certain types of content can be loaded or executed. ```js title="custom-view-config.mjs" const config = { headers: { csp: { 'connect-src': ['https://api.stripe.com'], 'frame-src': ['https://js.stripe.com', 'https://hooks.stripe.com'], 'script-src': ['https://js.stripe.com'], }, }, // ... }; ``` The required [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) headers are inferred by default from the `cloudIdentifier` and the `env.production.url`. This includes the hostname where the Custom View is hosted and the hostname of the Merchant Center API Gateway. ## `headers.permissionsPolicies` An optional object to configure the [HTTP `Permissions-Policy` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy). The `headers.permissionPolicies` object is used only for local development. To enable these features for production, you need to instruct your hosting server to return the header with the modified values. The Merchant Center Proxy Router will then attempt to merge the values with the default ones. ```js title="custom-view-config.mjs" const config = { headers: { permissionsPolicies: { microphone: '()', camera: '()', payment: '()', usb: '()', geolocation: '()', }, }, // ... }; ``` ## `headers.strictTransportSecurity` An optional list to extend the [HTTP `Strict-Transport-Security` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security). ```js title="custom-view-config.mjs" const config = { headers: { strictTransportSecurity: ['includeSubDomains', 'preload'], }, // ... }; ``` ## `labelAllLocales` An optional list of localized fields `{ locale, value }` with translated labels for each custom view locale, available in the user profile. These values will be used when presenting the user with a list of available Custom Views in the Merchant Center views. If they are not configured, the `name` values will be used instead. ```js title="custom-view-config.mjs" const config = { labelAllLocales: [ { locale: 'en', value: 'Popular Channels' }, { locale: 'de', value: 'Beliebte Channels' }, ], // ... }; ``` ## `type` The required type of Custom View. Currently we only support the `CustomPanel` value. ```js title="custom-view-config.mjs" const config = { type: 'CustomPanel', // ... }; ``` ## `typeSettings` Depending on the Custom View type, different settings might be required. ## `typeSettings.size` In case the `CustomPanel` type is used, the `size` property is required. It defines the size of the Custom View panel. Supported values are: `SMALL`, `LARGE`. ```js title="custom-view-config.mjs" const config = { type: 'CustomPanel', typeSettings: { size: 'SMALL', }, // ... }; ``` ## `locators` Since Custom Views are rendered in the context of built-in Merchant Center applications, you need to define the specific views where the Custom View should be rendered. This configuration property is a list of identifiers of Merchant Center locations where the Custom View is allowed to be rendered. ```js title="custom-view-config.mjs" const config = { locators: ['products.product_details.general'], // ... }; ``` A locator follows the pattern `..`. The following list contains all the currently available locators: ### Products application - `products.product_details.general` - `products.product_details.variants` - `products.product_details.search` - `products.product_details.selections` - `products.product_variant_details.general` - `products.product_variant_details.images` - `products.product_variant_details.prices` - `products.product_variant_details.prices.edit_price` - `products.product_variant_details.inventory` - `products.product_variant_details.inventory.details` - `products.product_variant_details.inventory.details.add_inventory` - `products.product_variant_images.add_image` - `products.product_variant_prices.add_price` ### Categories application - `categories.category_details.general` - `categories.category_details.products` - `categories.category_details.external_search` - `categories.category_products.manage_storefront_order` ### Customers application - `customers.customer_details.general` - `customers.customer_details.addresses` - `customers.customer_details.orders` - `customers.customer_details.business_units` - `customers.customer_addresses.new_address` - `customers.customer_addresses.edit_address` - `customers.customer_orders.order_detail` - `customers.business_unit_details.general` - `customers.business_unit_details.associates` - `customers.business_unit_details.addresses` - `customers.business_unit_details.orders` - `customers.business_unit_associates.new_associate` - `customers.business_unit_associates.edit_associate` - `customers.business_unit_addresses.new_address` - `customers.business_unit_addresses.edit_address` - `customers.add_business_unit.business_unit_details` ### Orders application - `orders.order_details.general` - `orders.order_details.shipping_and_delivery` - `orders.order_details.returns` - `orders.order_details.payments` - `orders.order_shipping_and_delivery.create_delivery` - `orders.order_shipping_and_delivery.edit_delivery` - `orders.order_shipping_and_delivery.add_parcel` - `orders.order_returns.create_return` - `orders.order_returns.edit_return` ### Prices application - `standalone_prices.add_standalone_price` - `standalone_prices.standalone_price_details` ### Discounts application - `discounts.product_discount_details.general` - `discounts.cart_discount_details.general` - `discounts.cart_discount_details.custom_fields` - `discounts.discount_code_details.general` - `discounts.discount_code_details.custom_fields` - `discounts.generate_discount_codes` ### Operations application - `operations.import_log_details` ### Project settings application - `settings.project.store_details` - `settings.project.channel_details` # Use variable placeholders Variable placeholders are a way of injecting certain information into the "static" configuration file. ## Environment variable references To make the Custom View config reusable across different environments, you can use references to environment variables within the config file. References are specified with a special expansion-like syntax `${}` together with the prefix key `env:`. For example, to load an environment variable called `APP_URL`, you would use `${env:APP_URL}`. Imagine developing a Custom View that can be used in the same Regions (Europe and North America) as the commerce APIs. We can assign the `${env:CLOUD_IDENTIFIER}` reference to the field `cloudIdentifier` and pass the actual value using environment variables. ```js title="custom-view-config.mjs" const config = { cloudIdentifier: '${env:CLOUD_IDENTIFIER}', // ... }; ``` The `CLOUD_IDENTIFIER` environment variable can be provided in various ways. For example: - as an inline environment variable when running a script command ```console CLOUD_IDENTIFIER=gcp-eu mc-scripts start ``` - using a [dotenv](https://github.com/motdotla/dotenv) file ```bash title=".env-eu" CLOUD_IDENTIFIER=gcp-eu ``` ```console mc-scripts --env .env-eu start ``` - by defining the environment variables in your CI service You can also pass multiple references to the same value: ```js title="custom-view-config.mjs" const config = { additionalEnv: { authorityUrl: 'https://${env:IDP_URL}/${env:IDP_ID}', }, // ... }; ``` ## Intl message references This feature is available from version `20.8.0` onwards. References for Intl messages are specified with a special expansion-like syntax `${}` together with the prefix key `intl:`. For example, to load a translation message from the `en.json` file named `Menu.Channels`, you would use `${intl:en:Menu.Channels}`. This is useful when specifying [Custom View labels](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/custom-view-config#labelalllocales). ```js title="custom-view-config.mjs" const config = { labelAllLocales: [ { locale: 'en', value: '${intl:en:Menu.Channels}' }, { locale: 'de', value: '${intl:de:Menu.Channels}' }, ], // ... }; ``` The reference placeholder assumes that the Custom View has the translation files in one of the following locations: - `/src/i18n/data/.json` - `/i18n/data/.json` # Runtime application environment Much of the information specified in the Custom View config is injected into the runtime environment and available via the global variable `window.app`. The `environment` prop is parsed and injected into a React Context, making it available to the entire application. To access it, use the `@commercetools-frontend/application-shell-connectors` package. ```jsx import { useCustomViewContext } from '@commercetools-frontend/application-shell-connectors'; const MyComponent = () => { const applicationName = useCustomViewContext( (context) => context.environment.applicationName ); return
{`Welcome to the application ${applicationName}!`}
; }; ``` All the properties defined in the `additionalEnv` object are made available to the `context.environment` object. For more information, see [Custom user properties](https://docs.commercetools.com/merchant-center-customizations/tooling-and-configuration/commercetools-frontend-application-shell-connectors#custom-user-properties).