Add my site

Install the tag

The tag is one small script served from our own domain. Add it to your site and connect your consent controls where analytics requires permission.

Takes about two minutes

The tag

<script defer src="https://app.datastated.com/ds.js?v=2026-09-10-consent"
  data-site="acme.com" data-site-id="dst_YOUR_SITE_ID"></script>

This snippet starts tracking when it loads. Where analytics requires consent, add data-require-consent before loading it and connect your consent manager to ds("consent", "granted") on acceptance and ds("consent", "denied") on withdrawal. The gate waits without measurement until a grant; the attribute alone does not display a consent prompt. Follow the consent setup and withdrawal examples, including the pre-load queue. Loading the script only after acceptance is another option, but withdrawal still needs to stop the loaded tag.

Copy the exact snippet from your dashboard: the data-site-id identifies the installation. Verify ownership separately with the DNS TXT record or homepage meta tag shown on Verify your domain. Put the tracking tag in your <head>, or anywhere in the page. It loads deferred, is 9,930 bytes minified (about 9.9 KB, 4,364 bytes or about 4.4 KB gzipped), and never throws into your page: if our endpoint is ever unreachable, your site does not notice.

Upgrading an existing installation? Once this source release is deployed, replace your snippet's src URL with https://app.datastated.com/ds.js?v=2026-09-10-consent, or the matching proxy URL from your dashboard. Keep ?v=2026-09-10-consent on proxy script URLs too. Browsers may still have the old unversioned URL cached; deploying new code or changing cache headers cannot clear those copies. The release response uses public, max-age=300, must-revalidate. Check the requested URL and loaded script before testing acceptance, withdrawal and re-grant.

What it records

On each pageview the tag sends:

  • the hostname and path of the page
  • the referring URL, when the browser supplies one
  • campaign tags on the link (utm_source, utm_medium, utm_campaign, utm_term, utm_content), plus the indie shorthands ?ref=, ?via=, and ?source=, which count as the source when no utm_source is present
  • an ad click identifier when present: fbclid, gclid, gbraid, wbraid, gclsrc, ttclid, msclkid, twclid or li_fat_id
  • viewport width and the browser language
  • a random visitor identifier from one first-party cookie

A click on a link to another domain sends the destination's host and path. When the tab is hidden or closed, the tag reports how long the page was visible, capped at 30 minutes. Goal calls send their names, optional values and properties; scroll goals send their names. Order calls can send an order id, value and currency.

If your site calls identify, the tag sends your user id, any email you supply and up to ten properties. The server keeps the email's SHA-256 hash rather than the address; user ids and properties are stored as sent. With payment detection enabled, a Stripe success page carrying a Checkout Session id also reports that id with the visitor id. The server uses Stripe's payment record to determine the amount and deduplicate the charge.

From the request itself the server keeps the browser, device and operating system parsed from the user agent, the country, region and city its edge reports, and a daily-salted hash of the address; the address itself is never stored. No fingerprinting, no raw IP addresses stored, no third-party scripts or cookies. The full detail lives in the privacy policy.

Framework notes

Every framework below comes down to the same thing: get the one script tag into the rendered HTML. Each one also has its own page in the sidebar with the exact steps.

  • Plain HTML / static sites (Astro, Hugo, Jekyll, Eleventy): paste the tag into your base layout's <head>.
  • Next.js: add it once in your root layout.
  • React, Vue, Svelte single-page apps: paste the tag into index.html. Route changes are tracked automatically, see below.
  • WordPress: paste the tag into your theme's header template, or use any "insert headers" plugin you already trust.
  • Google Tag Manager: use a Custom HTML tag and connect it to your consent manager. Where analytics requires consent, use the tag's consent gate or a consent-dependent trigger, and handle withdrawal after loading. Follow the GTM guide and consent examples.
  • Webflow, Framer and site builders: paste the tag into the site-wide custom code slot for the <head>.
  • Shopify: skip the tag. The Shopify app installs its own pixel and brings the orders with it.

Single-page apps

The tag patches pushState and replaceState and listens for popstate, so client-side route changes count as pageviews on their own. No router integration, no manual trackPageview() calls, and a repeated render of the same path is not double-counted.

Apps that route on the URL fragment (/#/pricing) are the one exception: add data-hash-routing="true" to the tag and the hash becomes part of the path, with each hash change counted as a pageview.

Subdomains

Keep the same snippet on every subdomain and they count as one site: the tag's data-site names the site, so a visit that starts on blog.acme.com and buys on app.acme.com is one visitor with one journey. Nothing to configure.

Several domains

A checkout on a different domain (pay.acme.io beside acme.com) is two visitors by default, because cookies do not cross domains. Add data-allowed-hosts to the tag on both sites, each naming the other, and a click between them carries the visitor id in the link, so the buyer on one side is the visitor on the other. The tag reference has the exact rules.

Privacy behaviour

Exclude your own visits

To browse your own site without counting yourself, open your browser console on your site and run:

localStorage.datastated_ignore = "true"

That browser goes silent from the next page load: no cookie, no events, exactly as if a privacy signal were on. Repeat it per browser and per device you test from, and run delete localStorage.datastated_ignore to count again.

For rules that apply to everyone, your site's settings have an Exclusions section: excluded paths (exact, or /admin/* for everything under one) and excluded IP addresses. Matching visits are never recorded and never count toward your plan.

Verify it worked

Open your site in a normal browser window and click around. The setup checklist detects the first recorded pageview. Complete domain verification to open the analytics. If nothing arrives, walk the troubleshooting list.

Questions? Email us at hello@datastated.com.