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

<meta name="datastated-site-verification" content="YOUR_TOKEN">
<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 code from your dashboard: a verification meta line and the script tag. The data-site-id identifies the installation. Paste both lines together in your site's <head>. Check installation then finds the tag and confirms you own the domain in one step. If you can't edit the <head>, use the DNS TXT record on Verify your domain instead. The tag loads deferred, is 10,230 bytes minified (about 10.2 KB; 4,498 bytes or about 4.5 KB gzipped), and never throws into your page: if our endpoint is ever unreachable, your site does not notice.

Upgrading an existing installation? If your snippet predates 2026-09-10, replace its src 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.

Install with your AI agent

If your site is code you edit (Next.js, WordPress, or custom HTML), hand the install to an AI coding agent like Claude Code or Cursor. The app's install screen has a Copy prompt for your AI agent button that copies a ready-to-paste prompt with your exact tag. Or write your own from this:

Install the DataStated analytics tag on my site so it loads on every page.
Add it site-wide, just before </head> in the shared layout, once. Don't
change the src or the data- attributes:

<meta name="datastated-site-verification" content="YOUR_TOKEN">
<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>

The meta line proves I own the domain. It must end up in the <head>
of the server-rendered HTML (not injected by JavaScript), so keep it
with the script tag.

If the site sends a Content-Security-Policy (a response header or a
<meta http-equiv> tag), add https://app.datastated.com to both
script-src and connect-src in the same change, or the browser will
silently block the tag.

When you're done, tell me how to publish or deploy so I can confirm it's live.

Replace data-site, data-site-id and the meta line's content with the exact values from your dashboard. Once the change is live, Check installation finds the tag and confirms you own the domain in one step. If the meta line can't reach your server-rendered <head>, use the DNS TXT record on Verify your domain instead.

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 two lines of tracking code into the <head> of 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.

Two switches sit in the same section. Don't count my team's visits is on by default: when you or a teammate open the dashboard over IPv6, visits from that network stop counting until 30 days after you were last seen on it. Shared IPv4 addresses are never learned this way, so add a home IPv4 address to the IP list yourself. Count visits from cloud servers is off by default, so visits from rented cloud servers (Amazon, Google Cloud, Oracle, DigitalOcean), which are almost always crawlers, don't count. Turn it on only if real visitors reach your site through a cloud-hosted VPN or office network. Orders always count.

Verify it worked

Open your site from a different network than the one you use for the dashboard (your phone with Wi-Fi off works) and click around. By default, DataStated leaves out visits from any IPv6 network you or a teammate opened the dashboard on, and visits from cloud servers, including many VPNs (see Exclude your own visits). The setup checklist detects the first recorded pageview, and the same check confirms you own the domain, which opens the analytics. If nothing arrives, walk the troubleshooting list.

Questions? Email us at hello@datastated.com.