Skip to main content

Tracking setup

This page describes how to set up tracking on your website. It covers the two channels your data reaches Webmarketer through, which should not be confused:

  • Sending page views is handled by the tracking script. It sets the visitor identification cookie and sends a page view on every navigation. This is what Webmarketer builds sessions, interactions and traffic origin from.
  • Sending events is handled by the Webmarketer API, never by the script. These are your conversions (purchase, form submission, sign-up, and so on), the ones that become events in your reports.

The two channels meet through the identifier set by the script: sent along with the event, it links that event to the visitor's browsing, and therefore makes it attributable to the traffic sources that led to it.

Loading the script​

By default the script can be fetched from https://cdn.ndrstnd.io/ndrstnd-v1.js, or, if you configured a tracking subdomain, from https://{your subdomain}/scripts/ndrstnd-v1.js, for example https://ndrstnd.acme.com/scripts/ndrstnd-v1.js.

The script can be added directly to a website, but we recommend using the following snippet so the commands issued through the global ndrstnd function are stored in a queue until the script has finished loading:

<script>
(function (w, d, s, u, n, e, a) {
w["NDRSTND_ALIAS"] = n; w[n] = w[n] || function (cb) { (w[n].q = w[n].q || []).push(cb); };
e = d.createElement(s); e.src = u; e.async = 1;
a = d.getElementsByTagName(s)[0]; a.parentNode.insertBefore(e, a);
})(window, document, "script", "https://cdn.ndrstnd.io/ndrstnd-v1.js", "ndrstnd");

// with a tracking subdomain, for example ndrstnd.acme.com:
// })(window, document, "script", "https://ndrstnd.acme.com/scripts/ndrstnd-v1.js", "ndrstnd");
</script>

In this example, the last two parameters passed to the function configure, respectively:

  • the URL the script is fetched from
  • the name of the global function defined on the window object used to talk to the API (ndrstnd from here on)

Sending page views​

Page views feed the reconstruction of sessions and interactions. They are sent by the script, to the collection infrastructure.

The ndrstnd function runs commands as callbacks whose first parameter is the client used to talk to the API (this pattern makes it possible to defer running the commands until the script is loaded).

ndrstnd(function(client) {
// code to run
});

Creating a tracker​

A tracker is an object created by the client that sends data to the API for a specific project. To create a tracker, call the client's createTracker method.

ndrstnd(function(client) {
const tracker = client.createTracker("projectId");
// with a tracking subdomain, for example ndrstnd.acme.com:
// const tracker = client.createTracker("projectId", { ndrstndDomain: "ndrstnd.acme.com" });
// ...
});

The createTracker method takes the Webmarketer project identifier as its first parameter. It also accepts, as a second parameter, an object that configures the tracker.

ndrstnd(function(client) {
const tracker = client.createTracker(
"projectId",
// default option values:
{
cookieName: "ndrstnd", // name of the JavaScript cookie set by the script
cookieDomain: "auto", // domain the JavaScript cookie must be set on
name: "default", // tracker name (useful when several trackers are created with the same client)
ndrstndDomain: `ndrstnd.io`, // tracking domain (e.g. `ndrstnd.acme.com` with a subdomain)
spaCompatibilityEnabled: true, // enables compatibility with SPA applications
},
);
// ...
});

Declaring several trackers is usually unnecessary, but when several Webmarketer projects have to receive the data, create one per project, each with a different cookieName.

When the script loads, a JavaScript cookie is set on the website; by default that cookie is named ndrstnd. To avoid a possible conflict, the cookie name can be changed by setting the cookieName value.

By default the script sets the JavaScript cookie on the highest possible level domain, which lets a set of subdomains of your website share the same cookie. That behavior can be changed by setting the cookieDomain value.

Invalid domain

If the configured domain is neither the current domain nor a parent of it, a warning appears in the console and the cookie is set on the highest possible level domain (the default behavior).

name​

The tracker name, useful to tell apart the trackers created by the client when there are several of them.

ndrstndDomain​

By default the script talks to the API on the ndrstnd.io domain. When a project is configured to use a tracking subdomain, the configured subdomain must be provided in the ndrstndDomain option (for example ndrstnd.acme.com).

spaCompatibilityEnabled​

This option enables automatic compatibility with SPA (single-page application) applications.

How it works

show more

A page's referrer is the URL of the website the visitor came from. Webmarketer uses that information to analyze which search engine, social network or other website brought you traffic.

To count sessions correctly, Webmarketer needs the referrer to be set properly, otherwise users' browsing sessions cannot be built correctly.

In SPA applications, the page referrer is not updated while navigating, which distorts how sessions are built. To work around that, the tracking script uses the previous page view as the referrer of each page view sent (for the first page view, the referrer is set to document.referrer).

I want to implement a different behavior

show more

If you want to implement a different behavior, disable this option and implement your own logic to provide the referrer to the tracker.

Here is an example of setting the referrer manually:

ndrstnd(function(client) {
const tracker = client.createTracker("projectId", { ndrstndDomain: "ndrstnd.acme.com" });
tracker.send("pageview", {r: "https://acme.com/page-1"});
});

Retrieving a tracker​

An already created tracker can be retrieved through the client's getTracker method. With no argument, it returns the tracker named default, the one createTracker creates when the name option is not set:

ndrstnd(function(client) {
const tracker = client.getTracker();
// ...
});

If several trackers were created, pass the name of the one you want to retrieve:

ndrstnd(function(client) {
const tracker = client.getTracker("trackerName");
// ...
});

This is the method used to retrieve the tracker of an already loaded page, for example to read the visitor identifier when sending an event.

Listing trackers​

The names of the trackers created with the client can be listed through the getTrackers method.

ndrstnd(function(client) {
const trackers = client.getTrackers();
console.log(trackers);
// ["tracker1", "tracker2", ...]
});

Sending a page view​

A tracker's send method sends a navigation hit to the collection infrastructure.

tracker.send("pageview");

The send method takes:

  • the message type to send (here pageview) as its first parameter
  • an optional object as its second parameter, to add information to the message as key/value pairs
Page views

For user sessions to be consistent in Webmarketer, it is important to send a pageview message every time the user navigates to a new page of the website.

Integration examples​

<script>
(function (w, d, s, u, n, e, a) {
w["NDRSTND_ALIAS"] = n; w[n] = w[n] || function (cb) { (w[n].q = w[n].q || []).push(cb); };
e = d.createElement(s); e.src = u; e.async = 1;
a = d.getElementsByTagName(s)[0]; a.parentNode.insertBefore(e, a);
})(window, document, "script", "https://cdn.ndrstnd.io/ndrstnd-v1.js", "ndrstnd");

// create a tracker for project "projectId" and send a pageview
ndrstnd(function(client) {
const tracker = client.createTracker("projectId");
tracker.send("pageview");
});
</script>

Sending events​

Events (purchase, form submission, sign-up, and so on) do not go through the script: they are sent to the Webmarketer API. The two channels are separate and complementary:

Tracking scriptEvents API
What is sentpage views (hits)events (purchase, form submission, sign-up, and so on)
Destinationthe collection domain (ndrstnd.io or your subdomain)https://api.webmarketer.io
What Webmarketer does with itinteractionsattributed events

An event is therefore sent through the Webmarketer API, on either of the following two routes:

  • POST /events: asynchronous ingestion. The 200 response confirms the call was accepted, not that the event is valid; an invalid event ends up in the trash in the interface.
  • POST /events/sync: synchronous ingestion. The 200 response is only returned once the event has been fully processed.

Unlike the rest of the API, these two routes do not require a service account: they can be called directly from the browser.

The eventType field must reference an event type declared in your project, and the data object must match its schema.

The trackerId field is what connects the two channels: it holds the value of the cookie set by the tracking script. Webmarketer uses it to find the visitor and their interactions, and therefore to attribute the event to the traffic sources behind the visit.

Without a trackerId, the event is still ingested, but it can only be linked to a user through reconciliation on their personal data (email, phone number, and so on).

That value is read on the tracker, with the get method and the fc key (for first party cookie). On page load, where the tracker is created:

ndrstnd(function (client) {
// with a tracking subdomain: { ndrstndDomain: "ndrstnd.acme.com" }
var tracker = client.createTracker(projectId, { ndrstndDomain: domain });
tracker.send("pageview");
var trackerId = tracker.get("fc");
});

get("fc") must be called after createTracker: that method reads or sets the cookie, so it is what makes the value available in the browser. Whether that value is usable by Webmarketer is a separate condition, described below.

Since the client is shared by every call to ndrstnd, an already created tracker can be read later with getTracker:

ndrstnd(function (client) {
var trackerId = client.getTracker().get("fc");
});
Sending from your server

If the event is sent from your backend (for example when an order is confirmed), it is up to you to pass that value from the browser to your server, then to set it as trackerId. On the server side, the value can be read from the cookie whose name was chosen when creating the tracker.

The page view must have been sent too

Having the value is not enough. Webmarketer resolves the trackerId against the collection infrastructure, which only knows an identifier once a page view has carried it. As long as that cookie has not been seen in any hit, the event is held, then ingested without being linked.

So send your events from pages where the script is installed and has already sent its pageview, not from a page that would only create the tracker.

Example​

The page view is sent once, on page load. Sending the event is isolated in its own function, called at conversion time, and reuses the tracker that already exists:

var PROJECT_ID = "projectId";

// on every page of the website, on load
ndrstnd(function (client) {
var tracker = client.createTracker(PROJECT_ID);
// with a tracking subdomain, for example ndrstnd.acme.com:
// var tracker = client.createTracker(PROJECT_ID, { ndrstndDomain: "ndrstnd.acme.com" });
tracker.send("pageview");
});

// to call at conversion time, for example when an order is confirmed
function sendPurchase(order) {
ndrstnd(function (client) {
// The tracker was created on page load, so the trackerId value can be read.
var trackerId = client.getTracker().get("fc");

fetch("https://api.webmarketer.io/api/v1/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
projectId: PROJECT_ID,
eventType: "purchase",
nonce: order.id,
trackerId: trackerId,
data: {
email: order.customerEmail,
turnover: { amount: order.total, currency: "EUR" },
},
}),
});
});
}

getTracker() returns the tracker named default. If your website creates several of them, pass the name you want (see name).

The nonce field is used to deduplicate the event: two calls carrying the same projectId, eventType and nonce less than 24 hours apart create a single event. So reuse a stable identifier of your own (here the order number) rather than a random value.