Documentation

Script options

Every attribute the snippet accepts: test mode, debug logging, and the privacy signals.

How options work

Every option rides on the script tag itself, as a data- attribute. There is nothing to configure in code and nothing to import. A missing attribute means the server decides; false and 0 are the only falsey values, so an attribute is on unless you spell out otherwise.

The two attributes you cannot leave off are data-key and data-collector; everything below is optional and changes how the tracker behaves once it is loaded.

Every attribute

AttributeDefaultEffect
data-keyrequiredYour site's tracking key. Write-only; safe in page source.
data-collectorrequiredWhere events are sent. Set it so the tag works from any page.
data-debugoffLogs transport failures to the browser console. Useful while installing, off in production.
data-respect-gpconHonour Global Privacy Control. Brave, DuckDuckGo and Privacy Badger send it by default, so the browser you test in may be one of them.
data-respect-dntonHonour Do Not Track, in any of its spellings.
data-require-consentoffCollect nothing until your banner calls oa.consent('granted'). Off by default, because measurement here is aggregate and first-party.
data-storage"local"Set to "none" for strict mode: no localStorage or sessionStorage at all.

One attribute is weaker than it looks, on purpose

data-respect-gpc="false" cannot make GPC visitors countable. Our servers discard any request carrying the Sec-GPC header regardless of the snippet, so the attribute only controls whether the browser bothers sending. The DNT attribute works as written; GPC is the signal with legal force, and it is enforced on both ends.

Strict storage mode

data-storage="none" tells the tracker to neither write to nor read from localStorage and sessionStorage. Use it when a strict policy forbids client storage of any kind. It has real costs, because the things that normally persist now last a single page load:

  • The per-tab session hint resets, so a session may split across page loads.
  • The offline queue is gone, so an event that fails to send while the tab is closing is not retried on the next load.
  • The consent state is not remembered between pages.
  • #oa-ignore does not work, because its whole store is localStorage.

Example: a separate staging install

Create a separate site for staging and use its own tracking key, so staging traffic never mixes into production charts. Turn on debug logging while you wire it up.

staging <head>html
<script
  async
  src="https://c.getopen.so/oa.js"
  data-key="YOUR_STAGING_SITE_KEY"
  data-collector="https://c.getopen.so"
  data-debug="true"
></script>
An older data-test-mode attribute is retired and ignored: traffic from snippets still carrying it is ordinary, visible and billable. Separate sites are the way to keep environments apart.

What the script does on its own

With no options at all, the tracker records pageviews (including client-side route changes), engagement time (visible time, and active time near a real interaction), Core Web Vitals, and the events you mark up. Pageviews send immediately; everything else batches for about a second and leaves via sendBeacon when a tab closes, so nothing is lost to navigation.

Site-level behaviour, the heartbeat cadence, the redacted query keys, your no-code rules and sampling, comes from your site's configuration and updates without touching the snippet.

What it never does

No cookies, no identifier stored on the device, no fingerprinting, no keystrokes, no form values, no session replay. The full list, with the reasons, is on the privacy and consent page.