---
title: Install on a custom site
description: Add the Dozenfold script to a custom storefront, wire consent and funnel stages, map page types and verify the first sessions.
updated: '2026-10-06'
slug: install-custom-site
---

# Install on a custom site

A custom site is any storefront that is not installed through the Shopify app: a headless or
framework frontend, or a Shopify theme where you add the script yourself. After
[onboarding](/docs/custom-storefronts) you have a **site id** and a public **ingest token**. The
token can only send events; it cannot read anything.

## 1. Add the script

Load the SDK once per page, as early as practical, and start it when it has loaded:

```html
<script async src="https://cdn.dozenfold.com/sdk/v1.js" id="dozenfold-sdk"></script>
<script>
  document.getElementById('dozenfold-sdk').addEventListener('load', function () {
    window.Dozenfold.init({
      siteId: 'site_…',
      token: 'omz_pub_v1_…',
      origin: window.location.origin,
      consent: 'unknown', // updated by your consent banner, see step 2
      release: 'web@2026.10.06', // optional: your build id
      currency: 'EUR', // optional: default for order values
    });
  });
</script>
```

In a single-page app (React, Vue, Next.js, Nuxt), load it in the root layout, not per route. Page
views on client-side navigation are captured automatically.

## 2. Connect consent

Collection follows the `consent` value. Call `setConsent` from your banner whenever the visitor
decides:

```js
// Accepted analytics
window.Dozenfold.setConsent('granted');
// Declined, but your policy allows anonymous measurement
window.Dozenfold.setConsent('cookieless');
// Declined
window.Dozenfold.setConsent('denied');
```

`cookieless` stores nothing in the browser and sends no identifier. Replay and `identify` need
`granted`. If you already know the visitor's choice when the page loads, pass it to `init` directly.

## 3. Report the journey

Dozenfold builds the funnel, page groups and revenue impact from journey stages. Call `funnel` where
your app knows them:

```js
Dozenfold.funnel('product_viewed', { product_id: product.id });
Dozenfold.funnel('product_added_to_cart', { product_id: product.id });
Dozenfold.funnel('checkout_started');
Dozenfold.funnel('checkout_completed', { order_value: order.total, currency_code: order.currency });
```

`checkout_completed` with an `order_value` turns impact into money. Without it, impact reads as
missed orders per day. The full list of stages is in the [SDK reference](/docs/sdk-reference#funnel).

## 4. Map your page types

Shopify-style paths (`/products`, `/collections`, `/cart`, `/search`, `/checkout`) are recognised
without configuration. If your product pages live at `/p/…` or your listing pages at `/shop/…`, map
them so journeys and page groups line up:

```js
pageTypes: { pdp: ['/p'], plp: ['/shop'], checkout: ['/pay'] }
```

## 5. Report handled errors and your framework's errors

Errors your code catches are not reported automatically. Send the ones that matter:

```js
// Vue
app.config.errorHandler = (error) => window.Dozenfold.captureException(error);
// React error boundary
componentDidCatch(error) { window.Dozenfold.captureException(error); }
```

## 6. Allow the hosts in your CSP

If the site sends a Content Security Policy, allow:

- `script-src https://cdn.dozenfold.com`
- `connect-src https://ingest.dozenfold.com https://cdn.dozenfold.com`

## 7. Verify

Open the live site in a normal browser, accept analytics, and browse a product, the cart and the
checkout. Within a few minutes the session appears in **Sessions** and the Overview leaves its
empty state. Pass `debug: true` to `init` to see in the console why something was not sent.

Automated browsers are not collected: Playwright, Puppeteer, Selenium, Lighthouse and headless
Chrome sessions are dropped on purpose, so test with a regular browser. See
[No data is appearing](/docs/no-data) if nothing shows up.

## Next steps

- Upload source maps from CI so stacks point to your code: [Source maps](/docs/source-maps).
- Mark each deploy as a release: [Releases](/docs/releases).
- Turn on [Error-session replay](/docs/replay) and [Slack alerts](/docs/alerts).
