Skip to content
Docs

How-to

Send workspace and custom events from your website with the Emailit tracking script and a public tracking key. Install it, track events, identify visitors and limit the key to your sites.

Available onPay as you goProBusinessCustomUpdated Oct 20, 2026

The tracking script sends events from your website: product views, sign-ups, items added to a cart. It needs no setup call; the tracking key is part of its URL. This page explains how to create a key, add the script, track events and tie them to your visitors.

Before you begin

  • The tracking script is included with Pro, Business and Custom plans. On Pay as you go you can’t create tracking keys, and the script’s requests return 403, also with keys created before a move to Pay as you go.
  • To create tracking keys in the dashboard, you need the Admin role in the workspace. With the API, use a key with Full Access.
  • You need to be able to edit your site’s HTML, or add a custom HTML tag in your tag manager.

Create a tracking key

Tracking keys are public: they go into your web pages, so anyone can read them. They can only send workspace and custom events, never read data, and you can limit them to your own sites.

  1. Open Tracking. Go to Email APIEvents, select the Tracking tab, then Create tracking key.

  2. Name the key. Enter a Name that says where it’s used, such as Online shop.

  3. Limit it to your sites. Under Allowed origins, enter your sites one per line, for example https://shop.example.com or *.example.com. Leave it empty to accept any site. See Allowed sites.

  4. Create it. Select Create. The Tracking tab now shows the snippet with your key filled in.

Add the script

Paste both tags into every page, ideally before </head>, with your key in place of TRACKING_KEY:

HTML
<script>window.emailit=window.emailit||function(){(window._emailitq=window._emailitq||[]).push(arguments)};</script>
<script async src="https://js.emailit.com/track/TRACKING_KEY/events.js"></script>

The first tag queues calls made before the script loads, so you can call emailit(...) right away. The script loads asynchronously, never throws into your page and also works from a tag manager.

  • If the Emailit forms script is on the page too, keep both. They share window.emailit.
  • If your site uses a Content Security Policy, allow https://js.emailit.com in script-src and connect-src.

Track events

JavaScript
// Custom event: any name after "c:", any properties
emailit("track", "c:product.viewed", { sku: "TS-42", price: 19.9 });

// Workspace event: checked against its definition
emailit("track", "w:customer.type", { segment: "b2b" });

The type must start with c: or w:; the script ignores other calls. Properties that aren’t an object are sent as {}. You can pass a third argument with occurred_at, an ISO 8601 date-time, for events that happened earlier.

The script doesn’t record page views by itself. Track the pages and actions you care about, for example a c:page.viewed event on each route change of a single-page app.

Shop commands

For online shops, the script also has product, cart, purchase and page commands. They record product views, carts and orders for Commerce and send them to the event log as the system events product.viewed, cart.updated and order.placed. Commerce is in alpha and open to the Emailit team only; elsewhere these commands are rejected. See Connect your shop.

Identify visitors

Once you know who the visitor is, for example after they sign in or subscribe, tell the script:

JavaScript
emailit("identify", { email: "jane@example.com" });
// or, if you store Emailit contact IDs:
emailit("identify", { contact_id: "con_2wPq7Lm3XcN8bV1zKd4RtY6sHf9" });

Every later event carries that email or contact ID, on this page and on later visits, so Emailit can tie it to the contact. When the visitor signs out, forget them:

JavaScript
emailit("reset");

reset also starts a new anonymous visitor ID, so the next person on a shared computer isn’t mixed up with the last one.

Events with an email that no contact has are kept, and they show on the contact once it exists. A contact_id that doesn’t match a contact is dropped from the event, without an error, so a public key can’t be used to test which contact IDs exist.

Anyone with your tracking key can call identify with any address, so Emailit doesn’t let the script’s events drive automations. They’re recorded, show on the contact and reach webhooks, but don’t start, end or advance automation runs. Send events that should do that from your server with the Events API. Each event from the script that names a contact has identity_verified: it’s true only when a signed link in one of your emails identified the visitor, which is part of the Commerce alpha, and those events do drive automations.

What the script sends

Each event carries, besides your type and properties:

Field Content
anonymous_id A random visitor ID (anon_…), kept in the browser’s local storage.
email, contact_id What you passed to identify, if anything.
context.page The page url, path, title and referrer.
context.campaign The page’s UTM parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content), as source, medium, name, term and content.
context.locale, context.timezone The browser’s language and time zone.

Emailit adds identity_verified to events that name a contact (see Identify visitors) and stores the browser’s user agent. It doesn’t store IP addresses, and the script sets no cookies. It keeps the visitor ID under emailit:aid and the identity under emailit:identity in local storage; if local storage is blocked, they last only for the page.

Events are collected for a moment and sent together, at most 20 at a time. When the visitor leaves the page, the rest are sent with sendBeacon.

If you need consent for analytics on your site, load the script only after the visitor agrees.

Allowed sites

allowed_origins limits which sites can send events with a key. Each entry is one of:

Entry Matches
https://shop.example.com Exactly that origin: scheme, host and port.
shop.example.com That host on any scheme or port.
*.example.com example.com and every subdomain.

An empty list accepts any site. Emailit checks the Origin header that browsers send with every request, so other websites can’t send events with your key. A script outside a browser can set any header, though, so treat browser events as untrusted input and send orders and payments from your backend.

Invalid events

Unlike the API, the script’s endpoint stores the valid events of a request even when others are invalid. Invalid events are dropped, for example a w: event with a property of the wrong type, or an event of a new type once the workspace uses its plan’s number of event types. Use debug to see why.

Debug

Turn on logging in the browser console in any of these ways:

  • Call emailit("debug", true).
  • Add data-debug to the script tag.
  • Open the page with ?emailit_debug=1 in the URL.

The console then shows each event and Emailit’s answer, including the reasons for rejected events.

Troubleshooting

Answer in the console Cause Fix
403 Origin not allowed for this tracking key The page’s site isn’t in Allowed origins. Add it, for example both https://example.com and https://www.example.com, or use *.example.com.
403 This tracking key is disabled The key is turned off. Turn it on in the Tracking tab.
403 Website tracking is included with Pro and Business. The workspace is on Pay as you go. Upgrade to Pro or Business.
404 Unknown tracking key The key in the script URL was deleted or mistyped. Copy the snippet again from the Tracking tab.
422 with every event in rejected None of the events was valid. Check the reasons in rejected.
429 The key sent too many events in a short time. Send fewer events per visitor, for example no event per scroll or mouse move.
Nothing at all An ad or tracking blocker stopped the script, or it isn’t on the page. Test in a browser without blockers and check that the snippet is there.
Scopes, names and where events go.
Define events and their properties.
Create, update and delete keys.
For orders and payments.

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.