1. The four surfaces
Kessel is four different things in a browser and they behave differently, so "what does Kessel store" depends which one you are looking at.
| Where | What it is | What it sets |
|---|---|---|
| usekessel.com and our documentation site | Marketing and documentation | Google Analytics, and on the documentation site a light-or-dark preference |
| The Kessel app: the console and the register | Signed in, used by you and your staff | A session token and your chosen location in localStorage, plus Google Analytics on the signed-in console pages |
| A guest check or a pay link, served by the same app | A customer paying their own bill at a table, or from a link you sent them | A token in sessionStorage for the life of the tab. No analytics: these pages load nothing third-party except Stripe and the web font. |
| A merchant’s storefront, on the merchant’s own domain | A customer ordering ahead from a shop | Nothing of ours: no analytics, no cookie, no storage. The web font is fetched from Google Fonts, which sets none either. |
2. Google Analytics
Google Analytics 4, measurement ID G-8C763ENZYN, sets first-party cookies named _ga and _ga_G-8C763ENZYN to count visits and see which pages get read. They last two years unless you clear them. Google receives your IP address, your user agent and the pages you view.
- Google Signals and the advertising features are switched off, so this does not build an advertising profile of you and is not shared with advertisers.
- No merchant record, order, customer, amount or receipt is ever sent to Google. The analytics tag sees a page; it does not see a sale.
- In the Kessel app it loads only on a signed-in console page. The surfaces one of your customers reaches — a pay link, a guest check, a booking page, a receipt — load no analytics and nothing else third-party except Stripe and the web font, because a page with an embedded payment form has to account for every script on it.
- Opt out for every site at once with Google’s browser add-on at tools.google.com/dlpage/gaoptout, or block googletagmanager.com. Nothing on any Kessel surface changes if you do.
3. What the app keeps, and why none of it is a cookie
| Key | Where | What is in it | How long |
|---|---|---|---|
| kessel.session | localStorage, on the Kessel app | Your session token, its expiry, and your business’s public id | Until you sign out or it expires. The app deletes it itself once the expiry has passed, rather than sending a token it already knows is dead. |
| kessel.storeId | localStorage, on the Kessel app | Which of your locations the console is acting on, as a number | Until you change it or clear your browser data. It is per browser on purpose: the tablet bolted to the counter in the second café should stay on the second café, and it is the same login as the first. |
| kessel.guest.session | sessionStorage, on the Kessel app | The token for a guest check opened by scanning the code on a table | The life of the tab |
| kessel.paid.… | sessionStorage, on the Kessel app | The receipt for a pay link you have already paid, so reloading the page shows the receipt instead of asking for the money again. The key ends in the last twelve characters of the link token rather than the whole of it, so it is not a second copy of a credential sitting at rest. | The life of the tab |
| kessel-docs-theme | localStorage, on the documentation site | Light or dark | Until you change it |
The session token is in localStorage rather than in a cookie, and that is a security decision rather than an oversight. The app and the API are on different hostnames, so a session cookie would have to be SameSite=None — which is exactly the configuration cross-site request forgery exploits. A token sent as an Authorization header cannot be attached to a request by somebody else’s page at all.
The trade is that a cross-site scripting bug could read it. The mitigations are that the API renders no user-supplied HTML, the app writes no raw HTML anywhere, and a session is short-lived and can be revoked on the server on the next request. We would rather publish that trade than describe a cookie we do not set.
None of these leaves your device, with one exception: the session token, which goes to our API on the request it authenticates. Your customers’ records and your sales are not in browser storage and are never sent to Google.
4. The offline queue, which is not browser storage
The tablet register keeps a sale taken with no connection in a database inside the app on the device — SQLite, not your browser — and shows it as queued rather than as captured until it has actually reached us. Cash only: a card cannot be taken offline.
It stays on the device until it flushes, and it is the one piece of Kessel storage on a device that holds order detail, which is why it is named here even though no cookie is involved. A device that is lost with queued sales on it is a device holding those sales; lock it the way you would lock a till.
5. Turning it off
- Analytics: Google’s own opt-out add-on at tools.google.com/dlpage/gaoptout covers every site at once, or block the script. Nothing on any Kessel surface behaves differently.
- Marketing and documentation pages: block everything. There is nothing there to break.
- The console and the register: the session token IS being signed in. Block storage for the app and you can still sign in and sell, because the app treats storage being unavailable as "not signed in" rather than crashing — but you will be signed out again on every reload.
- Private browsing, cleared site data and storage switched off are handled everywhere a key is read. A read that fails is treated as absent, because a cashier in a private window should get a sign-in page rather than a blank screen.
Also: Terms of Service. Pricing is $49 a month and interchange + 0.90% + 30¢, described in full on the pricing page.