Cookies and browser storage
Everything Popfinch can write to a visitor's device, why, for how long, and what it waits for before writing anything at all.
- Version
- 0.1
- Effective
- 2 September 2026
- Last updated
- 2 September 2026
No cookies is not the same as no storage
Popfinch sets no cookies. It does use localStorage and sessionStorage on the visitor's own device, and under the rules that govern storing or reading information on somebody's terminal equipment those are treated the same way as cookies. So this page lists them rather than resting on the word.
Nothing here leaves the device. These values are read by the script to decide whether to show a widget; they are not sent to us and there is no identifier that outlives a visit.
What is waited for
A project set to wait for consent — the default for a new one — stores nothing and counts nothing until the page says it may. Widgets still render, and a form somebody chooses to fill in is still sent, because neither of those requires storing anything on the device.
A rule that cannot be answered without a memory the script does not have fails closed. “Returning visitors only” is not shown rather than guessed at, and an A/B test with no measurement is not run: everybody sees the first arm.
The alternative setting, consent handled elsewhere, means the customer asserts their own tooling blocks this script until the visitor has agreed. Popfinch cannot see whether it does; that setting is a statement by the customer, not a check by us.
Every key
| Key | Store | Purpose | What it is for | Lifetime |
|---|---|---|---|---|
| pk_d_<widget> | local | personalisation | The day it was last shown, for “once a day”. | Until cleared |
| pk_e_<widget> | local | personalisation | That it has been shown, for “once, ever”. | Until cleared |
| pk_n_<widget> | local | personalisation | How many times it has been shown, for the lifetime cap. | Until cleared |
| pk_c_<widget> | local | personalisation | When it was dismissed, for the quiet period after a close. | Until cleared |
| pk_conv_<widget> | local | personalisation | That this person subscribed, so it stops appearing. | Until cleared |
| pk_seen | local | personalisation | That this is not their first visit. | Until cleared |
| pk_v | session | personalisation | This visit's answer to the above, so every page agrees. | The tab |
| pk_s_<widget> | session | personalisation | That it has been shown this visit. | The tab |
| pk_sid | session | personalisation | An identifier for this visit; an A/B test draws its arm from it. | The tab |
| pk_pv | session | personalisation | Pages seen this visit, for “not before their Nth page”. | The tab |
An earlier version kept pk_uid, a random identifier in local storage that survived every visit and was used for A/B allocation. It was withdrawn. The arm is now drawn from the visit, and the script deletes the old key from any browser still carrying it.
Three purposes
- Functional — rendering the widget the site owner configured, and handling a form the visitor chose to fill in. Writes nothing to the device.
- Personalisation — every key in the table above. Remembering that this browser has seen something, so a rule about frequency means anything.
- Analytics — the view, click, close and step beacons, and the A/B allocation that measuring them rests on.
Each purpose is granted separately and takes effect immediately. Withdrawing stops the beacons and deletes every key Popfinch wrote. Consent itself is never stored: remembering the answer would mean storing something in order to avoid asking whether we may store things.
Checking it rather than believing it
The consent documentation has the developer steps: load a page with a live widget in a private window, filter the network panel for the beacon endpoint, and look at local and session storage for any key beginning pk_. On a project set to wait there should be neither until consent is granted in the console, and both should disappear when it is withdrawn.