Skip to main content
Shopify stores get on-site tracking from the storefront pixel, installed for you when you connect the store. The browser SDK gives every other site the same events: custom storefronts, headless shops, marketplaces, booking and reservation sites, and SaaS marketing sites. Once installed, these events arrive exactly like a native integration’s, so the same automations work:

Anonymous visitors are not lost

Most people browse before they ever type an email address. The SDK keeps that history:
  1. A visitor browses anonymously. Their events are held in their browser. The SDK still pings the endpoint so the dashboard’s lastUsedAt shows the snippet is alive, but nothing is stored server-side for an anonymous visitor - the server answers queued: false.
  2. The visitor signs in or reaches checkout. Your backend mints a short-lived identity token, and your site calls sequenzy.identify(email, token).
  3. The held events are replayed against that contact at their original timestamps.
So a shopper who browses three products and then signs in arrives with all three on their timeline, not just whatever they do afterwards. Buffered history lives in the visitor’s own browser, so it does not follow them to a different device or survive them clearing site data. If a different person identifies on the same browser, the buffer is discarded rather than replayed onto the wrong contact.

Step 1: Create a tracking key

In the dashboard, go to Settings → Integrations → Website tracking and create a key. Or from the terminal:
The key is publishable: it ships in your page source and anyone can read it. That is by design, and it is why it can only append anonymous storefront events — never read contacts or reach the rest of the API. An origin allowlist limits browser misuse, but it is not identity proof because non-browser callers can forge an Origin header. Identified events therefore also require a signed, short-lived identity token minted by your backend.
A bare domain is read as https. https://*.example.com covers subdomains at any depth but not the apex, so list https://example.com separately if you need both. Add your development origin (for example http://localhost:3000) while you are wiring things up.

Step 2: Install the snippet

Paste the snippet from the dashboard or CLI into every page. Its first script creates lightweight method stubs synchronously, so calls made while the SDK is still downloading are queued rather than lost:
The snippet embeds both the key and your workspace id, so use it as printed rather than rebuilding it - a wrong workspace id fails silently. You can call the normal API immediately, including before the async loader finishes:
Pre-load calls run in order as soon as the SDK loads.

Install from npm

If your site has a JavaScript build, install the side-effect-free package and create the client explicitly:

Step 3: Identify your visitors

Call identify as early as your backend has authenticated someone - on sign-in, and again at checkout. First mint a token from your backend using a secret API key with commerce:write, automations:trigger, and subscribers:write (the last one because minting can create the contact). Pass the same publishable key that is in your snippet:
Tokens last 24 hours by default (ttlHours accepts up to 720). Mint a fresh one on each sign-in and at checkout rather than reaching for a long lifetime - the token is a bearer proof, and a short expiry is what limits a leaked one. Minting also establishes the email as a contact if it is not one yet, so identified events always have a profile to land on. The contact is created active with no list memberships and no automations triggered - enroll it through your normal signup flows when you want more than event attribution. Return only identityToken to that signed-in browser, then pass it with the same normalized email:
The token is bound to the workspace, tracking key, email, and expiry. A copied publishable key or forged email cannot trigger sequences, segment changes, or cart/browse recovery. Never expose the secret API key in browser code. Call reset() on sign-out so the next person using that browser starts clean:

Step 4: Track events

Each event has a convenience method:
providerProductId is your own product id. Use the same value you push to the product catalog so recommendations and product blocks in emails resolve to the right item.
Cart abandonment needs the cart contents, so include quantity on every cart event. Without it, a recovery email cannot say what was left behind.

When a cart disappears without telling us

The tracked cart is only as current as the events your site sends. Plenty of sites empty a cart without ever firing a removal: a session-scoped cart timing out, a reservation or inventory hold being released, the shopper finishing checkout on another device, or the snippet simply not loading on a page. So a tracked cart expires. After expireAfterHours (default 72) with no activity, the cart is dropped instead of being emailed about, and a later add starts a fresh cart rather than merging into the old items. That is what stops a recovery email from listing things the shopper no longer has. Sites using the browser SDK currently always use the default expiry. sequenzy shopify settings update --cart-expire-after-hours applies per connected Shopify store only - it has no effect on SDK-tracked carts. The cleanest fix is still to tell us directly - call sequenzy.viewedCart({ ... }) with the current contents whenever your site knows them, or fire removedFromCart when the cart empties. An explicit cart view replaces the whole snapshot, so it corrects any drift in one call - including sequenzy.viewedCart({ lineItems: [] }), which clears the tracked cart so no abandonment email goes out for items the shopper no longer has.

Configuration

Extra attributes on the script tag: The stored identity only applies while its identity token is also unexpired, so with the default 24-hour token the browser stays identified for at most a day after the last identify call regardless of this setting. data-sequenzy-identity-ttl-days caps the window from the other side. Lower data-sequenzy-identity-ttl-days on any site where one device is routinely shared between buyers rather than belonging to one of them - shared workstations, kiosks, in-store terminals, or any flow where people commonly buy on someone else’s behalf. A stored identity means “this browser was last used by this person”, not “this browser belongs to this person”, and a long window on a shared machine can attribute one person’s browsing to another. Setting data-sequenzy-storage="off" disables the anonymous buffer as well, so visitors who identify later arrive with no prior history. Use it only where a consent policy requires it.

Server-side alternative

If your visitors are signed in, you do not need the browser at all. Post the same events from your backend with your secret API key:
This is often the fastest way to get cart recovery live: it covers every signed-in shopper with no front-end work. The browser SDK then adds the visitors who browse before they sign in.

Managing keys

MCP exposes the same operations as list_web_tracking_keys, get_web_tracking_key, create_web_tracking_key, update_web_tracking_key, and delete_web_tracking_key. See the MCP reference. Revoking a key stops its events within about a minute while keeping the key value visible, so you can still find the matching snippet on your site. Delete it once the snippet is gone.

Troubleshooting

No events arriving. Check the key’s lastUsedAt. If it is null, no event has successfully authenticated yet: the snippet may be missing or not loading, the page may not have fired an instrumented event, or the origin allowlist may be rejecting the request. Open your site’s network tab and look for a POST to /customer-events and its response status. Events rejected with 403. Either the page’s origin is not on the key’s allowlist, or an identified event has a missing, expired, or mismatched identity token. Note that https://example.com and https://www.example.com are different origins, as are http and https. Anonymous history not appearing. Confirm token minting succeeds and sequenzy.identify(email, identityToken) runs at sign-in and checkout. Without a valid proof, events stay anonymous and are never attached to a contact. Nothing works in an ad-blocked browser. Some blockers drop third-party tracking scripts. Those visitors are covered by the server-side approach above if they sign in.