Skip to content
Twinpage

Snippet privacy and consent

Effective 1 October 2026

For website owners who install the Twinpage snippet. This page describes what the snippet does; it is not legal advice.

In plain words

What this snippet does

It shows some visitors a different version of a page you choose, and counts how many saw each version and how many completed your goal.

What it sends to us

Your site key and the snippet's version when a page loads; when a visitor sees a test or completes a goal, the test, the version, whether it was a view or a goal, and for an extra goal which one. If you turn on custom JavaScript, the visitor's browser also asks us for that code.

What it does not do

It sends us no form input, page content, logins, payments or passwords. The snippet itself does not set cookies (custom JavaScript you add is your own code). It does not follow visitors to other websites. It does not send the visitor ID, and its own requests contain no page address; like any web request, they carry the browser's normal Referer, which can include the page address depending on your site's referrer policy.

Where to put it

Put it on your public pages (home, pricing, landing pages). Keep it out of logged-in areas such as a dashboard or CRM.

Consent

Depending on where your visitors are and how your regulator treats A/B testing, you may need their consent before the snippet loads. That is your decision as the site owner; the privacy page explains how.

The honest part

Like any analytics or chat script, it runs with the permissions of the page it is on. That is why we recommend public pages only. You can also limit what it may load with your site's content security policy.

What the snippet stores in a visitor's browser

The snippet uses the browser's local and session storage. It does not set cookies.

KeyStorageWhat it holds
st_vidLocal storageA random visitor ID
st_a:<experiment id>Local storageThe version the visitor was assigned
st_x:<experiment id>Local storageThat the visitor has seen the experiment
st_e:<experiment id>Session storageThat the view was already counted in this session
st_c:<experiment id>Local storageThat the conversion was already counted
st_c:<experiment id>:<metric id>Local storageThat an extra metric's conversion was already counted
st_pSession storageThe visitor's device type (desktop, tablet or mobile), traffic source (direct, search, social, email, paid or referral) and whether they visited before; only when an experiment uses targeting
st_t:<experiment id>Local storageWhether the visitor is in the experiment's audience ("1" or "0"); only when the experiment uses targeting

The visitor ID, the visitor profile (st_p) and the flags above stay in the visitor's browser and are never sent to Twinpage. The experiment and version (and, for an extra metric, the metric) are sent with each view or conversion, as described below, without any visitor identifier. If storage is blocked, the snippet keeps the values in memory for the current page view only.

What the snippet sends to Twinpage

  • When a page loads: your site key and the snippet's version number (to check the snippet is installed and to fetch your running experiments).
  • When a visitor sees an experiment or converts: your site key, the experiment, the version, whether it was a view or a conversion, and, for an extra metric, which metric.
  • If a version uses custom JavaScript: a request for that code (see below).

The snippet itself does not send the visitor ID, the page's content, or anything typed into a form; custom JavaScript you add is your own code and is covered below. As with any web request, the visitor's IP address and browser details reach our servers and our hosting provider's logs. We do not store them in our database.

Google Analytics 4 (only if you turn it on)

Off unless you turn on "Send experiment data to Google Analytics 4" in a project's settings. Then, once per visitor per browser session for each experiment, the snippet passes a twinpage_exposure event to the Google tag or Google Tag Manager already on your page, with the experiment's ID and name, and the version's ID and name (for example Control or Variant B). That data goes from the visitor's browser to your own Google Analytics account; it is not sent to Twinpage. The snippet adds no visitor ID, page address or form input to it; Google Analytics records what it normally records with every event, under your settings. If you turn it on, mention it in your own privacy notice.

What the snippet does not do

It does not set cookies, follow visitors across other websites, or read form fields. It reads the elements your experiments select, to change them or to count clicks on them. If an experiment uses targeting, it also reads, in the visitor's browser, the browser's user-agent string and touch support (to tell device type), the page address's utm_medium parameter and the referring site (to tell traffic source), and keeps only the result in st_p. None of this is sent to Twinpage.

Custom JavaScript (only if you turn it on)

Off unless you turn on "Allow custom JavaScript on this project" in a project's settings (Growth plan). Then, for a version with custom JavaScript, the snippet loads your code from Twinpage with a normal script request. Like any script request, it carries the visitor's IP address, browser details and, depending on your site's referrer policy, the page address; we read none of it, and store and log nothing about the visitor (our hosting provider keeps its standard request logs). Your code then runs on your page with the same access as any other script on it. What it does there, such as setting cookies, reading forms or sending data elsewhere, is your processing, not ours, and the statements above about what the snippet does not do don't cover it. Describe it in your own privacy notice and consent banner.

Do you need consent?

Rules such as the EU and UK ePrivacy rules can require a visitor's consent before information is stored on their device, unless that storage is strictly necessary for something the visitor asked for. Whether A/B testing counts as strictly necessary differs between countries and regulators, and many treat it as needing consent. Other countries have their own rules. We cannot decide this for you: ask your legal adviser.

Loading the snippet only after consent

If you need consent, load the snippet only once the visitor has accepted the relevant category in your consent banner. Until it loads, nothing is stored and nothing is sent, and the visitor sees your original page. Call the function below from your consent banner when the visitor accepts:

<script>
function loadTwinpage() {
  var s = document.createElement("script");
  s.src = "https://twinpage.app/snippet.js";
  s.async = true;
  s.setAttribute("data-site-key", "YOUR_SITE_KEY");
  document.head.appendChild(s);
}
</script>
  • Replace the site key with your project's key from the Install snippet panel (under Advanced).
  • Use this loader instead of the dashboard's install block, not with it. The block's first two lines hide the page until the snippet runs; before consent the snippet never runs, so the page would stay hidden briefly on every page load.
  • The small stub that queues Twinpage.track calls before the snippet loads only keeps them in memory, so you can leave it in place.

If a visitor withdraws consent

Stop loading the snippet for them. To remove what it already stored, run this when they withdraw:

<script>
["localStorage", "sessionStorage"].forEach(function (name) {
  var store = window[name];
  Object.keys(store)
    .filter(function (key) { return key.indexOf("st_") === 0; })
    .forEach(function (key) { store.removeItem(key); });
});
</script>

Your own privacy notice

Your privacy notice should say that you run A/B tests and describe the storage above. You are welcome to link to this page.

Data processing agreement

For the visitor data the snippet handles, you are the controller and we are your processor. Our Data Processing Agreement forms part of our Terms of Service and applies automatically; you don't need to ask for it.