Shield · Data collection

Exactly what the SDK collects

Field-level transparency, per privacy mode — and the hard list of what is never read or transmitted.

Enforced on the server too

This page describes SDK 1.13.0. Where a field arrived later than 1.0, the version is given.

The limits on this page are enforced server-side as well as in the SDK: the ingest API rebuilds every payload from a strict allowlist and rejects sensitive-looking values (raw emails, phone numbers, card patterns, password-like fields), so bypassing the SDK cannot store undocumented data. Raw request payloads are never persisted.

Free Preview sites also contribute pseudonymized, infrastructure-level sightings to the FindIP Threat Network: network-level data only, identical in every privacy mode, never including anything from the sections below.

Collected

By privacy mode

In every privacy mode

  • Event name, timestamp and source (sent by your code, or detected by the SDK; a detected event also carries a confidence value and how it was detected)
  • Page URL, path, title and referrer
  • UTM parameters, and whether the URL carried a gclid or fbclid (yes or no, never the value)
  • Session ID, and where the browser keeps it (1.11.0)
  • SDK name, version and integration; in a mobile app's WebView, the app id you configure (1.13.0, see Mobile apps)
  • Browser user agent, language and time zone
  • The privacy mode in force and the consent state
  • On form events: form metadata and the form outline (1.8.0): field types, the labels printed on the page and the button text
  • Customer context and identity, only if your code provides them (see Customer context)
  • When a form has a response configured: which response ran and how it ended

balanced and advanced: everything above, plus

  • Visitor ID, and where the browser keeps it (1.11.0)
  • The browser's language list, platform, and whether cookies are enabled
  • Screen width, height and colour depth; viewport width and height
  • Whether the device supports touch
  • A form snapshot (1.9.0): a picture of a form with every value blanked, taken by one visitor's browser per form version, only when Shield asks for it

In SDK 1.12.0, advanced sends the same fields as balanced. The only difference in the payload is the retention hint (extended instead of standard).

strict: only the first list. No visitor ID, no localStorage, no screen or device details, and no form snapshot when strict is the mode you configured (see the consent case under Form snapshot).

The FindIP backend adds enrichment the SDK does not collect: visitor IP, ASN, geolocation, VPN/proxy/Tor/hosting/malicious flags, risk score and recommendation.

Never collected

In any mode, under any configuration

Form valuesWhat a visitor types or selects in a form: no field values of any kind, including passwords and payment card numbers.
Plain identifiersEmail addresses, phone numbers or user IDs in plain form. See Customer context for the hashed and encrypted forms your own code can send.
Behavior captureKeystrokes or mouse movement.
Screenshots and recordingsNo screenshot of the page or of the screen, and no session recording. The one picture Shield takes is the form snapshot: a single form, redrawn empty.
Page HTMLThe page's HTML is not sent. The form snapshot is drawn in the browser and only the finished image is uploaded.

Form metadata

Sent with form events: a form coming into view, a form being submitted

{
  "field_count": 2,
  "has_email_field": true,
  "has_password_field": true,
  "has_phone_field": false,
  "has_payment_field": false,
  "has_message_field": false,
  "submit_text_type": "signup",
  "form_id": "signup-form",
  "form_name": "signup",
  "form_action": "/signup",
  "outline": {
    "fields": [
      { "type": "email", "label": "Work email" },
      { "type": "password", "label": "Password" }
    ],
    "button": "Create account"
  },
  "outline_hash": "3fa9c1d2"
}
  • field_count and the has_* flags count the form's fields and say which kinds are present. They are worked out from each field's type, name, id, autocomplete, placeholder and aria-label attributes.
  • submit_text_type is a category for the submit button's text: signup, login, lead, checkout, payment, reset or generic.
  • form_id, form_name and form_action (SDK 1.3.0) are the form's id and name attributes and the path of its action (no host, no query string), each cut to 200 characters. They let the dashboard tell your forms apart.

Input values are never read or transmitted.

Form outline

Field types, labels and button text. SDK 1.8.0 and later, sent in every privacy mode

Form events also carry outline, so the dashboard can draw a recognisable mock of each form.

  • fields: up to 12 of the form's fields, in page order. Hidden inputs and buttons are skipped. For each field: its type (the input type, or select or textarea) and its label.
  • label is text from your page's markup, the first of these that exists: the field's <label>, its aria-label, its placeholder, its name.
  • button is the text of the submit button.
  • Every label and the button text is cut to 40 characters. Text that looks like an email address, a phone number or a card number is dropped, in the SDK and again on the server.
  • outline_hash (SDK 1.9.0) is an 8-character hash of the outline, the form's CSS class names and its approximate width. Shield uses it to notice that a form has changed.

The outline is what your page prints around the fields. It never contains what a visitor typed. If your page writes personal data into a label or a placeholder (for example a placeholder showing the signed-in user's name), that text is part of the outline unless the filter above drops it.

Form snapshot: a picture of the empty form

SDK 1.9.0 and later. Not taken when strict is the mode you configured; turn it off with captureFormSnapshots: false

Shield can show a real picture of each form in the dashboard, next to its events. The picture is taken in a visitor's browser. This section says exactly what is in it.

When a picture is taken. When a form comes into view, the SDK reports it. If Shield has no picture of that form, the form has changed since the last one, or the picture is more than 30 days old, the response asks that browser for one. Shield asks one browser at a time, so one visitor per form version takes the picture and everyone else does nothing. A browser tries once per form version per browser session (it remembers the attempt in sessionStorage).

When no picture is taken.

  • When the site's configured privacyMode is strict
  • When you set captureFormSnapshots: false (see the SDK reference)
  • When the browser asks for reduced data use (data saver)
  • While the tab is hidden; a tab that is never shown takes none

One case needs care. In SDK 1.12.0 the snapshot check reads the mode you configured, not the mode in force for the visitor. On a site configured as balanced or advanced with consentRequired: true and noConsentMode: 'strict', a visitor who declines consent is handled in strict mode for everything else on this page, but their browser can still be the one asked for a form picture. If that matters for your site, set captureFormSnapshots: false, or use noConsentMode: 'disabled' so that nothing at all is sent without consent.

What is drawn. Never the live form. The SDK copies the <form> element and, in the copy:

  • empties every text, email, password, number, date and other input, and every <textarea> and editable region
  • unticks every checkbox and radio button
  • resets every <select> to its first option
  • replaces every image with a blank pixel and removes its alt text
  • replaces every embedded frame, video, audio, canvas or object (a captcha widget, a payment frame) with a blank box of the same size
  • removes scripts

The copy is drawn off-screen with the page's own styles and encoded as a WebP or JPEG of at most 200 KB, covering at most 900 by 1200 CSS pixels of the form. The drawing library (html-to-image) is loaded from cdn.findip.net only at that moment.

What is uploaded. One request to /v1/shield/snapshot with the image, its width and height, your site key, the session ID, the page path, the form's form_id, form_name and form_action, and its outline_hash.

What is stored. The image, its size, the page path and the form's identifiers, one picture per form: a new picture replaces the old one. The session ID in the upload is not stored with the picture, so a picture is not linked to the visitor whose browser drew it. A form that has not been seen for 90 days loses its picture, and "Retake" in the dashboard deletes it at once.

What the picture can still show. Everything your page prints inside the <form> element as ordinary text: labels, placeholders, headings, help text, button text, the first option of each drop-down, and any error message visible at that moment. If your server prints personal data there as text rather than as a field value (for example "Signed in as [email protected]", a delivery address or an order summary inside the form), that text is in the picture, for the one visitor whose browser took it. If any of your forms does this, set captureFormSnapshots: false or use strict mode on those pages.

Browser storage

Two random IDs, and nothing else about the visitor

Cookies has the full list; in short:

  • Session ID: the _fip_sid cookie, copied to sessionStorage. A second cookie, _fip_ss, holds the same ID to mark that the session has started.
  • Visitor ID (not in strict mode): the _fip_vid cookie and, since SDK 1.11.0, a localStorage entry of the same name with the same lifetime.
  • When the browser refuses the session cookie (SDK 1.11.0): sessionStorage, then the tab's window.name, then, only if you switch on linkSession, a short-lived _fip parameter added to same-origin links at the moment they are clicked.
  • A sessionStorage entry named _fip_snap:<outline hash> records that this browser already tried a form snapshot, so it does not try again.

When the browser stores nothing. Some browsers refuse all of the above. So that the pages of one visit still count as one session, Shield then derives a session ID on the server from data the request already carries: your site, the UTC date, the visitor's IP address, and the browser's User-Agent and Accept-Language headers, passed through a keyed hash (HMAC). Nothing is stored in the browser for this. The ID changes every UTC day and is different on every site. A visitor ID is derived the same way, except in strict mode. Derived IDs start with sess_cl_ and vis_cl_.

Two people on the same network with the same browser version and language get the same derived ID.

Customer context

Sent only if your own code provides it, in every privacy mode. The only fields FindIP.track() accepts:

user_id_hash, email_hashHashed identifiers
email_domainDomain only (e.g. gmail.com)
account_age_daysAge of the account, in days
plan, currency, transaction_amountBusiness context
form_name, lead_sourceAttribution
customObject with safe string/number/boolean values

FindIP.identify() takes a plain user ID and email from your page and sends neither as given. It sends their SHA-256 hashes, the email's domain and, since SDK 1.1.0, a copy of each encrypted in the browser with your site's identity key (user_id_enc, email_enc). Only your Shield dashboard holds the key that opens them. See Identify users and add context.