Skip to content

Client-Side Tracking

The Gro tracking SDK is a lightweight browser library (about 5KB minified, 2KB gzipped) that captures page views, custom events, and user identities and sends them to Gro. Use it to power analytics, build segments, and trigger automations from real customer behaviour on your storefront or web app.

Every tracking call is authenticated with an API key.

  1. In the dashboard, go to Settings › API Keys and click New API Key.
  2. Give it a name and choose the SDK type. This is the key used for all tracking calls.
  3. The key is shown only once. Copy it and store it somewhere safe.

Keys look like gro_live_.... SDK keys are safe to embed in your public page source, so there is no need to hide them.

Paste this snippet into the <head> of your site. It loads asynchronously and will not block page rendering. Replace the key with your own.

<script>
!(function () {
var g = (window.gro = window.gro || []);
if (g.init && g._loaded) return;
g.methods = ["init", "track", "page", "identify"];
g.factory = function (m) {
return function () {
var a = Array.prototype.slice.call(arguments);
a.unshift(m);
g.push(a);
return g;
};
};
for (var i = 0; i < g.methods.length; i++) {
var k = g.methods[i];
g[k] = g.factory(k);
}
g.load = function (apiKey, opts) {
var s = document.createElement("script");
s.type = "text/javascript";
s.async = !0;
s.src = (opts && opts.sdkUrl) || "https://cdn.usegro.net/sdk/v1/gro.js";
var f = document.getElementsByTagName("script")[0];
f.parentNode.insertBefore(s, f);
if (apiKey) {
g.init(opts || { apiKey: apiKey });
}
};
g._snippet = !0;
})();
gro.load("gro_live_your_api_key_here");
gro.page(); // Track initial page view
</script>

The snippet queues any track, page, or identify calls you make before the SDK finishes loading, then replays them once it is ready, so you can start calling gro.* immediately.

If you build your frontend with a bundler, install the package instead:

Terminal window
npm install @gro/tracking-sdk

Then initialize it once when your app starts:

import gro from "@gro/tracking-sdk";
gro.init({
apiKey: "gro_live_your_api_key_here",
trackingUrl: "https://tracking.usegro.net", // optional
debug: false, // optional
autoPageView: true, // optional (default: true)
timezone: "Europe/London", // optional: the visitor's timezone, see below
});

With autoPageView enabled (the default), the SDK records a page view automatically on initialization.

Use gro.track(eventName, properties) to record any custom event:

// Track a custom event
gro.track("Product Viewed", {
product_id: "123",
product_name: "Premium Widget",
price: 29.99,
category: "Electronics",
});
// Track button clicks
gro.track("Button Clicked", {
button_id: "signup-cta",
location: "homepage",
});

Page views are recorded automatically on initialization. You can also record them manually, which is useful for single-page apps that change route without a full reload:

// Track a page view
gro.page();
// Track with a page name
gro.page("Product Page");
// Track with properties
gro.page("Product Page", {
category: "Electronics",
referrer: document.referrer,
});

Link an anonymous visitor to a known customer when they sign up or log in. Everything they did before identifying is stitched to their profile:

// Identify with email only
gro.identify("user@example.com");
// Identify with email and traits
gro.identify("user@example.com", {
firstName: "John",
lastName: "Doe",
plan: "premium",
});
// Identify with an object
gro.identify({
email: "user@example.com",
id: "user_123",
firstName: "John",
lastName: "Doe",
});

Identifying someone who already has a profile updates it. A first or last name you send replaces the one on the profile; a blank or missing name leaves it as is.

Any trait that isn’t a standard field (email, id, name, phone, timezone) is saved as a custom property on the profile, within a few minutes. In the example above, plan: "premium" becomes the plan property, ready for segments, merge tags like {{ person.properties.plan }} and flows.

  • Values can be text, numbers or true/false. A list is saved as comma separated text. Nested objects are skipped.
  • Send null to remove a property.
  • A later identify overwrites the value.

When you identify a visitor, the SDK sends their timezone so emails sent “in each recipient’s time zone” reach them at the right hour. By default it reads the timezone from their browser. That browser guess only fills a profile that has no timezone yet, so it never overwrites one you’ve set.

If your site knows the visitor’s timezone better (for example from their account settings), set it yourself. A timezone you set always replaces the one on their profile. Use an IANA name such as Europe/London:

// When you start the SDK
gro.init({ apiKey: "gro_live_your_api_key_here", timezone: "Europe/London" });
// Or once you know it
gro.setTimezone("America/New_York");
// Or for one identify call
gro.identify("user@example.com", { timezone: "Australia/Sydney" });
// Go back to the browser's own timezone
gro.setTimezone(null);

Signup forms send the same timezone when someone subscribes.

By default every event gets a unique auto-generated event_id. To guard against duplicates (for example when a customer refreshes an order confirmation page), pass your own event_id in the properties. Events sharing an event_id are stored only once:

gro.track("Order Completed", {
event_id: "ord_123", // Only the first event with this id is stored
order_id: "ord_123",
total: 99.99,
});

Every event the SDK sends is enriched for you:

  • Identifiers: a persistent anonymous ID and a session ID, stored in cookies so returning visitors are recognised.
  • Page context: page URL, title, referrer, and screen dimensions.
  • Timezone: on identify, the visitor’s timezone from their browser, unless you set one (see Visitor timezone).
  • Server-side enrichment: the tracking endpoint adds the user agent, IP address, and geo (country and city) from the request.

Not everything happens in the browser. To send events from your backend (order webhooks, cron jobs, subscription lifecycle events), see Server-Side Tracking.