Installation
Add the tracking SDK to a storefront, configure it with your public API key, and confirm it is running.
Add the snippet
Put this in <head>, below your <title> tag and above any code that calls trackbee:
<script>
window.trackbee = window.trackbee || (function () {
var q = [];
function stub(method) {
return function () { q.push([method].concat([].slice.call(arguments))); };
}
return { q: q, track: stub('track'), consent: stub('consent'), cartToken: stub('cartToken') };
})();
</script>
<script async src="https://cdn.trackbee.ai/g/trackbee-tracking-sdk.min.js" data-pak="pk_live_..." data-identity-mode="internal"></script>Replace pk_live_... with your store's public API key. That is both pieces: the small inline script, then the SDK itself.
Why below the title
Every event carries the page title, read at the moment the event is sent. The SDK starts as soon as its script runs, so a snippet placed above <title> can send an event while the title is still unparsed, and that event records an empty title.
Put it below <title> and there is nothing to think about. Anywhere else in <head> works too, as long as the title is already above it.
Now you can call trackbee from anywhere, at any time:
trackbee.track('product_view', {
product_id: '8472019',
variant_id: '4410228',
price: '29.99',
});Why the first script is there
The inline script is a stub. Until the real SDK starts, trackbee.track, trackbee.consent and trackbee.cartToken only record each call. When the SDK starts it replaces the stub and replays everything that was recorded, in order.
That buys you three things:
- Load order stops mattering. The SDK loads
async, so it never delays rendering, and calls made before it starts are not lost. - Nothing throws if the SDK never loads. An ad blocker or a CDN outage means the calls are recorded and quietly dropped. Your own code keeps working.
- Including it twice is safe.
window.trackbee || ...keeps whatever is already there, stub or real SDK.
Recorded calls are replayed in the order you made them, as soon as the SDK starts.
Do not hold a reference to the global
Write trackbee.track(...), not var tb = window.trackbee followed by tb.track(...) later. The SDK replaces window.trackbee when it starts, and calls made through a saved reference to the old stub go nowhere, with no warning.
Configure it
Both attributes on the script tag are required. If either is missing or invalid the SDK logs an error and does nothing at all: no events, no window.trackbee.
| Attribute | Value |
|---|---|
data-pak | Your store's public API key. You get this from TrackBee when the store is set up. |
data-identity-mode | internal or url. Nothing else, and there is no default. |
Identity modes
internal is what you want unless someone told you otherwise. The SDK generates a visitor ID the first time it runs and keeps it in the browser, so later visits are recognized as the same person.
url means the SDK does not generate or store anything. It reads the visitor ID from the _t_i and _t_i_ts query parameters on the current URL instead. Use this when something upstream already owns the visitor ID and passes it along in links.
Shopify custom checkouts always use url
If you are building a custom checkout for a Shopify store, use data-identity-mode="url". Never internal.
The shopper reaches your checkout from the Shopify storefront, and the visitor ID was already generated there. Your job is to receive it, not to make a new one. A custom checkout also usually runs on its own domain, and a stored visitor ID does not travel across origins, so internal has nothing to find and mints a fresh one.
That costs you the whole journey. The visitor who browsed and the visitor who checked out become two different people, and the ad that drove the order is credited to neither.
So have the storefront put _t_i and _t_i_ts on the link through to your checkout, and read them there. Carry the original cart token across in the same step: identity and cart both have to stay stable across that handover.
The visitor ID has to be a UUID
In url mode, whatever you pass in _t_i has to be a UUID, like 3f2a1c7e-9b4d-4e81-a0f6-5c2d8e7b1a93. Anything else is still sent with your events, but TrackBee cannot store that visitor's attribution, so their later conversions are not matched back to the ad that brought them in. The SDK logs an error when it sees one:
[TrackBee] The visitor id in the _t_i URL parameter must be a UUID. Received: "sess_84f1". Events are still sent, but this visitor's attribution cannot be stored.No surrounding whitespace
data-pak is used exactly as written. data-pak=" pk_live_1 " sends the spaces too and the key will not match.
Check it is working
Open the storefront with the browser console on. You are looking for two things.
1. The SDK logged its version.
[TrackBee] Tracking SDK v<version> — loaded<version> is whichever release is live on the CDN, so the number you see will not match this page. Only the shape matters.
If that line is missing, look for a [TrackBee] error instead. These are the ones that stop it starting:
| Message | What to fix |
|---|---|
No script tag with data-pak attribute found. TrackBee not initialized. | The script tag is missing, or has no data-pak. |
data-pak attribute is empty. TrackBee not initialized. | data-pak is present but has no value. |
data-identity-mode attribute is empty. TrackBee not initialized. | data-identity-mode is missing or has no value. |
data-identity-mode value must be either 'url' or 'internal', received: ... | Check the spelling. Only those two values work. |
No [TrackBee] output at all means the file never loaded. Check the network tab for a blocked request, usually an ad blocker or a content security policy.
2. A request goes out when you send an event.
Filter the network tab for trackbee, then send a page view from the console:
trackbee.track('page_view');You should see a request fire. The SDK sends nothing until you ask it to, so an idle page is correct, not broken.
Sending the page view
The SDK does not send one for you, and it does not watch for route changes. Send one when a page is shown:
trackbee.track('page_view');On a storefront that loads a fresh document per page, put that call in the page itself, after you pass consent. On a single page app, send one on the first render and one on every route change:
router.afterEach(() => {
trackbee.track('page_view');
});Next
- Send events for what happens on the storefront.
- Pass consent if you run a consent banner.