The browser tracker collects useful analytics without reading a full URL or creating a fingerprint. It sends only the page path.
<script defer src="https://api.datavisitors.com/assets/sg.js" data-key="YOUR-INSTALL-KEY"></script>
Page views and SPA navigation
The tracker sends sg_page_view when it starts. It also sends a page view after common SPA navigation.
It observes history.pushState, history.replaceState, and popstate. It does not intercept navigation.
The tracker creates a new session after 30 idle minutes. First-party random values identify the anonymous visitor and session.
Outbound links and downloads
The tracker records outbound_link when a clicked link resolves to another host. The property contains the destination origin and path.
The destination query string never leaves the browser.
The tracker records file_download for 26 common file extensions. These include PDF, CSV, ZIP, document, media, and installer formats.
A tagged link sends its tagged event only. It does not also send an outbound or download event.
Engagement
The tracker measures time only while the page is visible and focused. It keeps the maximum scroll depth from 0 through 100.
An engagement beacon sends only when it has new information. Three additional engaged seconds or a deeper scroll creates new information.
The tracker checks for new information on tab hide, page hide, and SPA navigation. Engagement extends the session activity time.
Engagement does not increase page views, custom events, interactions, or the Dashboard event count.
Choose your capture mode
The tracker has two modes. Manual is the default: nothing is captured beyond page views, outbound links, downloads, and what you tag or send yourself. Teams that want the PostHog-style firehose opt in on the install tag:
<script defer src="https://api.datavisitors.com/assets/sg.js" data-key="YOUR-INSTALL-KEY" data-autocapture="clicks,submits"></script>
clickssendssg_clickfor interactive elements (button, link,[role="button"], button-typed inputs) with ALLOWLISTED metadata only:tag,id, a textlabel(64 chars), and — for same-origin links — thehrefPATH. Never an input value, never a keystroke, never a foreign URL, never a query string.submitssendssg_submitwith the form'sid/nameonly — field values never leave the browser.data-sg-no-captureon any element excludes its whole subtree.- Consent gating, opt-out, host restrictions, and the ingestion shields apply to autocaptured events exactly like every other event.
A tagged element (data-sg-event) always wins over autocapture — a
click sends your named event, never both.
heatmapadds click COORDINATES tosg_click— as percentages of the page, never pixels of a screen — and only while the project's Heatmaps switch (Settings → Privacy) is on; the server drops them otherwise, whatever the tag says.vitalsloads a second small file (sg-vitals.js) that measures the Core Web Vitals of the page load — LCP, INP, CLS, FCP, TTFB — and sends onesg_vitalsbeacon when the page is hidden. Only while the project's Web vitals switch (Settings → Privacy) is on; the server refuses the beacon otherwise, whatever the tag says.
Script options
| Attribute | Value | Default | What it does |
|---|---|---|---|
data-key |
the project's install key | — | Required. Names the project every event belongs to. |
data-domains |
comma-separated hostnames | every host | The tracker stays inactive anywhere else. See Allowed origins. |
data-autocapture |
clicks, submits, heatmap, vitals |
off | Opt in to automatic capture, one comma-separated list. |
data-include-localhost |
present or absent | absent | Lets the tracker run on a development machine. |
On an element rather than the tag: data-sg-event and data-sg-prop-* name an event (Custom events), and data-sg-no-capture excludes a subtree.
When the tracker sends nothing
The tracker refuses to start in three situations. Each one is a decision made before anything is sent.
| Situation | Why | What to do |
|---|---|---|
A robot drives the page — navigator.webdriver, PhantomJS, Nightmare or Cypress |
a test run is not a visit | nothing; this is the point |
The page is a file: URL |
a document opened from disk is not a visit | serve the page over HTTP |
The page is on localhost, *.localhost, 127.*, [::1] or 0.0.0.0 |
a developer's own machine must not reach the production numbers | add data-include-localhost to the script tag while you test |
On localhost the tracker prints one console warning that names the attribute. The other two refusals are silent.
<script defer src="https://api.datavisitors.com/assets/sg.js" data-key="YOUR-INSTALL-KEY" data-include-localhost></script>
A page the browser prerenders runs its scripts before anybody looks at it. The tracker waits for the page to become visible, so a prerender that is never shown sends nothing. The server refuses a prerender's request too, with the code prefetch, for older copies of the tracker.
What happens next
- Custom events — tag an element, or call the API yourself.
- Cookieless by default — the privacy regimes, consent modes and the opt-out switch.
- Counting correctly — what breaks when a server sends page views too.