Analytics data posture.
LAST UPDATED · September 17, 2026 (first published)
This page exists to be handed to whoever reviews your install. It describes the mag.js tag field by field: what leaves the browser, what never does, what is protected before it is sent, and every switch you control. If you are looking for how magig handles your data as a customer, that is the privacy policy. This page is about your visitors.
The short version: auto-capture is designed to be safe to leave on inside an authenticated product. Record ids are stripped from paths, query strings are dropped unless named, and text inside form controls is never read. All three are on by default, with no configuration.
01What every event sends
Each event carries this envelope:
- project key — your public tracker id, the one visible in the script tag.
- anonymous id — a random identifier stored in a first-party cookie or localStorage. Not derived from anything personal, and not shared across our customers.
- session id — a random id that groups one visit.
- timestamp — when the event fired, from the browser clock.
- page URL and path — after redaction (section 03). Id-shaped path segments are replaced and unnamed query parameters are removed before sending.
- referrer — when present, redacted the same way. Inside an app the referrer is the previous screen, so it gets identical treatment.
- attribution — campaign parameters from the landing URL (
utm_*,gclid,fbclid,ttclid,ref), so your own dashboard can attribute a signup to the ad that produced it. - user agent — the browser UA string, truncated to 1 024 characters. On arrival it is parsed into device type, browser and OS; the raw string is not stored on the event.
Event-specific fields: a click adds the element tag, its visible text (first 120 characters, subject to masking), its element id, its link target and the click coordinates plus viewport size for heatmaps. A scroll adds only a depth percentage. A conversion or identify adds exactly what you pass to window.mag.track() or window.mag.identify() — those are your own calls, and we send what you put in them.
02What it never sends
- Anything typed into a form. Text is never read from
<input>,<textarea>,<select>or<option>elements. Not truncated, not hashed — not read. - Keystrokes. There is no keylogging of any kind.
- Page content at large. We capture the element a visitor clicked, not the document around it. There is no DOM snapshot and no session replay.
- Your visitors’ IP addresses. The request IP is used transiently to look up a country, then discarded — it is never written to the events table.
- Third-party tracking cookies. Storage is first-party only, scoped to your domain, and never used to follow a visitor to anyone else’s site.
- Data pooled across customers. Your visitors’ events belong to your project.
03Protections that are on by default
These require no configuration. A founder who pastes the snippet and reads nothing else still gets all three.
- Path templating. Id-shaped path segments are replaced before sending, so
/requests/df7b4d99-898b-4b10-929d-6d0ee58a4be3is sent as/requests/:id. Matching is by shape, not position, and the shapes are deliberately conservative: a content slug like/pillar/clinica-medica/module/gastroenterologiapasses through untouched. Over-templating is visible and recoverable; under-templating is silent, so the rule errs toward leaving readable words alone. - Query allowlisting. Only named parameters survive — the campaign parameters in section 01. Everything else is dropped, including parameters we have never heard of. This is an allowlist and not a denylist on purpose: a denylist keeps the one parameter nobody thought to enumerate, which is reliably the one carrying a token or a record id.
- Click-text masking. Text is never taken from form controls, or from anything inside an element marked
data-mag-private. A masked element sends no text field at all rather than a placeholder.
Link targets and element ids go through the same redaction as any URL, because href="/invoices/91f8-…" and id="invoice-12345" are two of the most direct ways a record id escapes a click.
04What you can switch
All of these are attributes on the script tag.
data-exclude-paths="/app/*,/admin/*"— turn auto-capture off entirely on matching routes. Matched against the real path, before templating. Your owntrack()calls still fire, so a signup behind an excluded prefix is still measured.identify()still records who the visitor is — later conversions carry it — but sends no event of its own from an excluded route.data-mask-text=".client-name,.amount"— never send text for elements matching these selectors.data-capture-query="utm_source,plan"— replace the default allowlist when you need a specific parameter kept.data-template-paths="false"— opt out of path templating. Worth saying plainly: this makes capture less private, and exists for apps whose paths carry no ids.data-disable="true"— the tag loads and does nothing.data-mag-private— not a script attribute but a marker you put on any element in your own markup. Nothing under it reports text.
Add data-debug="true" while configuring and the SDK logs what it sends, and warns in the console when a data-mask-text selector matches no element — so a typo is not mistaken for protection.
05Verifying this yourself
None of the above needs to be taken on faith. Open your network tab, filter for the ingest request, and read the JSON — the redaction runs in the browser, before the request is sent, so what you see in that payload is the entire set of what leaves. The tag is served unminified enough to read at assets.magig.app/mag.js.
Client-side is a deliberate choice. Redacting on our servers would mean the value had already crossed the wire, which is a promise rather than a control.
06Questions
Anything this page does not answer — including a specific field your reviewer needs a ruling on — goes to hi@magig.app. If you find something the tag captures that this page does not describe, tell us and we will treat it as a bug in the tag or a bug in this page.