Skip to content

Content-Security-Policy

If your shop sends a Content-Security-Policy header (or a <meta http-equiv> equivalent), the browser blocks anything the policy does not allow. This page lists exactly what the Ziex Try-On widget needs. It describes the widget as released today (phase 1); the section What changes next says what is planned.

You do not need any of this when your page has no CSP.

What to allow

Directive Value to add Why
script-src https://api.ziex-tryon.com The widget (tryon-embed.js) and the loader (tryon-loader.js) are served from the API host.
connect-src https://api.ziex-tryon.com Every request the widget makes (sending a try-on, status, the list of categories, the saved copy of a result) goes to the API host.
img-src https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob: plus your own image hosts media.ziex-tryon.com serves the result pictures; data: is used for previews of the shopper's photo; blob: for the thumbnails and the full-size view in "My looks". Product pictures are loaded through <img>, so the hosts that serve them (your shop's or its CDN) must be allowed here.
style-src 'unsafe-inline' The widget puts a <style> element into its own shadow root and uses a few inline style attributes.

Notes:

  • The widget does not use frame-src, font-src, media-src, worker-src or object-src.
  • Product pictures are not fetched with connect-src. The widget loads them as images, so img-src is the directive that matters for them. If the CDN sends CORS headers, the widget downsizes the picture in the browser; without them it sends the picture's address instead and our server fetches it.
  • If your policy has no script-src, connect-src or img-src, the browser falls back to default-src. Add the hosts to whichever directive your policy actually has.

A complete header

A shop that serves everything from its own domain and its product pictures from cdn.shop.example:

Content-Security-Policy: default-src 'self'; script-src 'self' https://api.ziex-tryon.com; connect-src 'self' https://api.ziex-tryon.com; img-src 'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:; style-src 'self' 'unsafe-inline'

The same policy with one directive per line, to read it more easily (a header must be a single line):

default-src 'self';
script-src  'self' https://api.ziex-tryon.com;
connect-src 'self' https://api.ziex-tryon.com;
img-src     'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:;
style-src   'self' 'unsafe-inline'

Add the Ziex Try-On hosts to the policy you already have; do not replace it. Keep your other directives as they are.

As a <meta> tag

If you cannot set headers, a <meta> tag in <head> works for these directives:

<meta http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self' https://api.ziex-tryon.com; connect-src 'self' https://api.ziex-tryon.com; img-src 'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:; style-src 'self' 'unsafe-inline'">

Put it before the first <script>. A <meta> policy cannot carry frame-ancestors, report-uri or sandbox; those need a real header.

Two things that are blocked under a strict policy

1. The inline onerror of the product preview. The window shows a small preview of the garment. If the picture cannot be loaded, the widget hides it with an inline onerror handler. Under a script-src without 'unsafe-inline' that handler is blocked, so a broken preview stays on screen as a broken-image icon. It is cosmetic: the try-on itself is not affected. Make sure the product picture address is correct and the host is in img-src.

2. Inline configuration from a CMS. The usual way to pass the configuration is an inline script that calls TryOn.init({ … }), for example one added by wp_add_inline_script in WordPress. Under a strict script-src an inline script is blocked unless it carries a nonce or a hash. Use the nonce mechanism of your CMS or framework, or move the init() call into a small script file you serve yourself and allow with 'self'.

A nonce or hash in style-src turns 'unsafe-inline' off

Browsers ignore 'unsafe-inline' in a directive that also contains a nonce or a hash. If your style-src has one, the widget's <style> element is blocked and the window is drawn without its styles. Until a nonce is supported (see below), style-src must contain 'unsafe-inline' without a nonce or a hash.

'strict-dynamic'

With 'strict-dynamic' the browser ignores host names in script-src. Give your own <script> tags the nonce instead. The loader adds the widget script from code, which 'strict-dynamic' allows when the loader itself was allowed by a nonce. Check it in the console as described below.

How to check

  1. Open the product page with the browser's developer tools open on the Console tab. Open the window and press "Try on" (a test key is enough). The browser prints a line for each blocked request, such as Refused to connect to 'https://api.ziex-tryon.com/…' because it violates the following Content Security Policy directive: "connect-src …". The directive named in the message is the one to fix.
  2. In the Network tab, a blocked request is shown as (blocked:csp).
  3. Roll the change out safely first with Content-Security-Policy-Report-Only: it takes the same value, blocks nothing and only reports. Add report-uri https://your-endpoint.example/csp (or report-to) to collect the reports from real visitors, and switch to the enforcing header when the reports are clean.

What each failure looks like:

What is blocked What you see
script-src No launcher and no TryOn object: window.TryOn is undefined.
connect-src The launcher is drawn (the check that hides it when your limit is used up fails open), but a try-on ends with a connection-lost message.
img-src Broken pictures: the garment preview, the result, or the thumbnails in "My looks".
style-src The window appears without its styles.

What changes next

A later release of the widget will remove the need for 'unsafe-inline' in style-src: the widget will be drawn without inline styles and will accept a nonce from the page. That is not released yet. Until it is, use the directives above. When it ships, this page will say so, and the directives here will keep working.

Related: Widget reference, Lazy loading and pickup.