Privacy Policy
Last updated: October 27, 2026
This Privacy Policy explains how StorePilot ("we", "us", "Platform") collects, uses, stores, and protects information when Clients use the Service, and what data the Plugin may collect about end-users on Client websites.
1. Who We Are
StorePilot is a SaaS analytics and monitoring platform, provided by Webity — its full details are in section 16 of the Terms of Service. For the purposes of this Privacy Policy:
- We are the Data Processor — we process personal data on behalf of our Clients according to their instructions.
- The Client is the Data Controller — the website owner who installs our Plugin and sends data to our Platform.
- End-Users are visitors to the Client's website whose data may be collected by the Plugin.
2. Data Collected by the Platform
2.1 Account Data (Client)
When you register on the Platform, we collect:
| Data | Purpose |
|---|---|
| Email address | Account identification, notifications |
| Password (bcrypt hashed, never stored in plain text) | Authentication |
| Name (optional) | Dashboard display |
| Account creation timestamp | Internal records |
We do not store payment card data. When an owner chooses a paid plan, Stripe takes the payment and receives the billing details of the person who subscribes — name, email, billing address, VAT number and payment card; we keep the plan, the invoice amounts and Stripe's customer reference.
2.2 Site Configuration Data
When you add a WordPress site to the Platform, we store:
- Site name and domain
- API key (used to authenticate data from the Plugin)
- Notification destinations — the email addresses, Slack and webhook URLs and Telegram chats you choose to send alerts to (URLs, bot tokens and signing secrets stored encrypted)
2.3 End-User Data Collected via the Plugin
The Plugin may collect the following data about visitors to the Client's website, depending on which features are activated:
| Category | Data Points | Feature |
|---|---|---|
| Technical | JavaScript errors, stack traces, error type | Error Tracking |
| Technical | Server-side error messages, severity, file/line, the session ID of the visit whose request raised the error (only when that request named one), and — from the Node SDK — the route TEMPLATE, HTTP method and status code | Backend Error Tracking |
| Technical | For failed AJAX calls: the request's field NAMES and a 500-character sample of the response | Error Tracking |
| Technical | The steps a visitor took just before an error, kept with that error — at most 20: pages navigated to, the element clicked (as a CSS selector, never its text), console messages, the page's own requests (method, address, status and duration; never headers or bodies, and no query string except the routing name WordPress and WooCommerce put there — action on admin-ajax.php, wc-ajax on the shop's own address), and the names of the Client's own named events with at most 3 of their attributes. Collected whether or not Session Recording is on | Error Tracking |
| Behavioral | Pages visited (full URL including query string), page title, time on page, session ID | Pageview Analytics |
| Behavioral | Clicks, rage clicks, dead clicks, scroll depth, element selectors | Heatmaps |
| Behavioral | On a WooCommerce checkout: the NAMES of the checkout form fields a visitor used (for example billing_phone), how many times each was focused and typed into, and how long it held focus. What was typed into a field is never collected, and card, password and other credential-shaped fields are skipped entirely | Checkout Field Analytics |
| Behavioral | Named events the Client's own page sends about what a visitor did (for example "opened the product configurator"), each with up to 10 short attributes of up to 100 characters, the page and the visit it happened on. Attribute names shaped like a credential or a contact field are refused, and an email address or telephone number inside an attribute value is masked before storage | Custom Events |
| Behavioral | Mouse movements, clicks, scroll, page content, keyboard input* | Session Recording |
| Behavioral | Network request metadata — method, URL, status, duration (never headers or bodies) | Session Recording |
| Behavioral | Browser console output** | Session Recording (opt-in, off by default) |
| Behavioral | Canvas content — the rendered pixels of <canvas> elements, captured as up to 8 image frames per second while a canvas is being redrawn***** | Session Recording (opt-in, off by default) |
| Technical | Text passed to console.error() by the site's own scripts, with a stack trace** | Error Tracking (opt-in, off by default) |
| Identity | WordPress User ID and role (if logged in) | Error Tracking, Leads; Campaign attribution — the visits of browsers logged in to the same account count as one buyer's |
| Contact | Name, email, phone, city/region/country. Street address and postcode are refused — see *** | Lead Capture (WooCommerce); Campaign attribution — the visits of browsers whose checkouts were filled in with the same email address count as one buyer's |
| Contact | Every named field of any contact form submitted, minus credential-shaped fields*** | Lead Capture (forms) |
| Conversation | Chat transcripts received from the Client's own chat provider (Brevo Conversations): the messages as they were typed, the visitor's name and email address as the provider reported them, and the page the chat began on. Where a message carried a file, the Platform stores the chat provider's own link to it and never a copy of the file itself; the file is shown in the dashboard by loading it from the provider. Card numbers and credential-shaped values are masked before storage; email addresses and telephone numbers inside a message are KEPT, because they are the contact detail the Client reads the transcript for and the same values already sit on the lead beside it****** | Conversations (opt-in, off by default) |
| Feedback | Answers to on-site surveys — scores, selected options and free-text answers****, with session and visitor identifiers | Surveys |
| E-commerce | Cart contents, cart total, order notes | Lead Capture |
| E-commerce | WooCommerce orders, reported by the Client's own server: order number, status, amounts, line items, coupon codes, payment method and the billing email address. Sent for every order whether or not the visitor consented to tracking or sent a Global Privacy Control signal — it is the Client's record of a sale, not tracking of the visit | Ecommerce |
| Network | IP address (used for geolocation; always truncated to a /24 for IPv4 or /48 for IPv6 before storage) | All features |
| Device | User agent, browser, OS, screen size, language, time zone | Visitor Analytics; Error Tracking (the browser and its version, the OS and the device type each error occurred in) |
| Location | Country code (derived from IP) | Visitor Analytics; Error Tracking (the country each error occurred in) |
| Image | A rendered PNG of a page. Produced either from a recorded visit, or from a copy of the page serialised in a visitor's own browser when a Client has asked for an image of that page *** | Heatmap backgrounds |
* Session Recording: all form input is masked by default — what is recorded is the length of what was typed, not the characters. Passwords are never recorded. Page text that the site itself rendered is not masked: an order confirmation showing a name and address will appear in the recording as the visitor saw it. A Client may un-mask specific fields by CSS selector, which is a deliberate choice they make per field.
*** Page images: when a Client asks for an image of one of their pages, the next few visitors of that page each send one serialised copy of it. It is masked in the browser by the same rules as Session Recording before it is sent, is never taken from a visitor who has declined tracking or whose browser sends a Global Privacy Control signal, and is deleted as soon as it has been rendered into the PNG. At most three copies are taken per page, after which the request stops.
** Console output is off by default and must be switched on per site — twice over, because these are two separate switches with two separate destinations: one puts console output inside a session recording, the other files what is passed to
console.error()as an error. When either is on, it captures whatever the Client's own scripts log — which can include API responses and cart contents — and no masking rule can reach it, because there is no element to mask.
*** Form fields. Every named field of a submitted form is stored, except that two families of field keep their NAME and have their VALUE replaced with the marker
[hidden]before anything is written — so a Client can always see which fields their form carried, and never what was typed into these ones:
- fields whose name is credential-shaped (
password,token,api_key,cvv,card_number,otp,ssn,date_of_birth,nonce,session,cookieand similar);- the street address and the postcode (
address_1,address_2,postcode, and theirbilling_/shipping_spellings). A shop needs to reach a customer, which is an email and a phone number; it does not need their door. This applies to the modelled address fields as well as to the raw form record, so the Platform holds no street address or postcode for a visitor at all.city,stateandcountryare kept — that is the same coarse geography already derived from the IP address.Values that are not refused outright still pass the automatic redaction floor described above. In a session recording, all of these fields are masked like any other input and cannot be un-masked by CSS selector.
This is a floor, not a guarantee: a sensitive field with an ordinary name is stored like any other, so a Client collecting special-category data in a form should exclude that page under Settings → Privacy → Excluded URLs.
**** Survey answers. Free-text answers pass the same automatic redaction floor as other free text — email addresses, long digit runs and credential-shaped values are replaced before storage — and the same caveat applies: it is a floor, not a guarantee. A visitor writes whatever they write; a Client asking open questions on pages where special-category data is plausible should not.
***** Canvas content is opt-in, off by default, and must be switched on per site. A canvas is rendered pixels — a signature pad, a product personaliser, a drawing tool — and no masking rule can reach into pixels, so whatever is drawn on a canvas is recorded exactly as drawn. A Client who enables it is responsible for ensuring their canvases do not display personal data, or for excluding those pages under Settings → Privacy → Excluded URLs. Pages without a canvas are unaffected.
****** Chat transcripts reach the Platform only if the Client connects a chat provider, and the direction is the reverse of every other integration on this page: the provider SENDS the transcript to the Platform on the Client's own configuration. The Platform never sends anything back to the provider and holds no credential for it. One thing does travel toward the provider, and not from the Platform: where the Client has embedded the provider's chat widget on their site, the collector hands that widget two pseudonymous identifiers —
STOREPILOT_VISITOR(the browser identifier above) andSTOREPILOT_SESSION(the visit) — inside the visitor's own browser, so that a transcript can be matched to the visit it began in. Nothing else is handed over, and it happens only where tracking is allowed: a visitor who refused consent, or who sends Global Privacy Control, is not announced to the widget at all.
3. Legal Basis for Processing
We process data on behalf of our Clients (as Data Processor). The legal basis for processing end-user data is determined by the Client (Data Controller). Typically this will be:
- Legitimate interests — for error tracking and technical analytics;
- Consent — for session recordings, which require explicit cookie/tracking consent from the visitor;
- Contract performance — for lead data submitted through checkout forms.
4. Data Retention
Retention runs automatically every night. These are the platform defaults:
| Data Type | Default Retention |
|---|---|
| Pageviews, scroll depth, custom events | 90 days |
| Individual clicks (position, element, moment) | 30 days — their daily totals stay in the heatmap grids below; while a site's older days are being recounted, at most 90 |
| Session recordings (rows and video files) | 14 days, or 3 days for a visit that showed nothing, or 24 hours for a visit that produced no recording at all, or for one judged automated or likely automated |
| Heatmap background images | 90 days (removed with the pages they belong to) |
| JavaScript / PHP errors | 180 days from the last time the error occurred |
| The steps a visitor took before an error, and the record that their visit met it | 180 days after that visit last met the error, even while the error itself keeps occurring — from November 3, 2026; until then, as long as the error is kept |
| Visitor records | 400 days, and only once no pageview, lead or recording still refers to them — a visitor judged automated or likely automated traffic goes sooner, see below |
| Leads | 365 days from when the lead was captured, unless the Client sets a different limit — from November 3, 2026; until then, kept until the Client sets a limit |
| Chat transcripts | 365 days after the last message, or the Client's own lead limit — a chat is the same person's own words as the form beside it, and one exchange does not get two windows. From November 3, 2026; until then, kept until the Client sets a limit |
| Orders | The order is kept with its amounts, status and dates; the customer's email address and the link to their visit, browser and lead are removed 365 days after the order was placed, or on the Client's own lead limit — from November 3, 2026 |
| Survey responses and answers | 365 days |
| Aggregated statistics (daily counts, heatmap grids) | 2 years |
| Automated-traffic verdict of each visit | 2 years, as long as the per-visit statistics it qualifies — from November 3, 2026 |
| Uptime check history | 30 days |
| Generated export files (scheduled CSV exports) | 7 days |
| Account data | Until account deletion |
| Audit trail of account and security actions (who, what, when, and the IP address truncated to a /24 or /48) | 730 days |
| Consent records (a visit's consent decision — granted or withheld — where it came from, and the visit and browser identifiers it applies to) | 730 days |
| Refresh tokens | 7 days (auto-expired and cleaned up daily) |
When an account is deleted, the comments, recording notes, lead status changes, follow-up sequence confirmations and support messages written from it stay with the team that shares them — they are part of that team's record — but are signed “deleted user” instead of the address. The audit trail keeps the email address recorded with each action until that entry expires, because a record of who did something cannot be rewritten by the person it describes.
A scheduled export produces CSV files on the platform's own disk. Each file is a copy of personal data the tables above already hold, so it is removed after 7 days — the download link in the dashboard then reports the file as expired. Recipients of the notification mail receive a link to the dashboard, never the file itself.
A recording that showed nothing — a single page, under ten seconds, no clicks, no error and no frustration — is removed after 3 days rather than 14. This is a shorter window inside the one above, never a longer one: nothing is kept for more time than the table states. The recordings list in the dashboard still shows such a visit until then; it is left out by default only when recordings are read through the API or a connected AI client.
A visit that produced no recording at all — the visitor left before the first fragment of footage could be uploaded, so the row names a page and nothing more — is removed after 24 hours. It is counted separately from the visits above, because "there is nothing to watch" and "it was not worth watching" are different facts about different visits.
A visit our classifier judges to be automated traffic — a crawler, a scraper, a synthetic monitor — or likely automated — a visit that left nothing behind (one page, no click, no form, no chat) and is indistinguishable from a crawler's — has its footage removed after 24 hours. The day is an appeal period rather than a delay: a first verdict is reached within the hour a visit ends and is re-checked the following night with every late signal in place, so nothing is destroyed before the check that could overturn it has run. Both kinds are reported as a statistic about the site, are excluded from the figures describing your customers and from the visit lists, and are credited back to your plan's event and recorded-session counts. A visit that left a form or a chat is never judged either way.
A visitor judged automated or likely automated traffic has its visitor record and page views removed after 10 days, unless it left a lead, an order, a chat or a recording, which keep it under the ordinary windows. The ten days outlast the nightly re-check of the last seven, for the reason above; the daily totals those page views were counted into are aggregated statistics and stay. A crawler typically starts every page in a fresh browser, so each page it loads would otherwise be kept as a separate visitor record for 400 days.
Leads, chat transcripts and the customer's identity on an order share one window, because they are one person's contact data: 365 days by default, from November 3, 2026. Until that date they are kept until the Client sets a limit, as they always were; the change was announced on the Announced Changes page fourteen days ahead, because it deletes data Clients already hold. A Client who needs a different period — shorter or longer; GDPR Art. 5(1)(e) storage limitation is the Controller's obligation — sets it under Settings → Privacy → Delete leads after, and that limit replaces the default for all three. An order itself is never deleted by retention: it is the Client's business record, so its amounts, status, dates and line items stay, and only what identifies the customer is removed.
Clients may delete any data at any time through the dashboard, and the right-to-erasure endpoint removes one visitor's data outright.
5. Data Storage & Security
- The Platform database is hosted on a dedicated server with restricted access.
- All data in transit is encrypted using TLS 1.2+.
- Session recording files are stored on the Platform's own server. Where a Client asks us in writing to keep their recordings in object storage the Client themselves owns and pays for, we will configure that for their site alone; those files then live in the Client's own cloud account, under their own access controls, and no storage provider of ours is involved. Recordings made before the Platform owned storage may still reside on the Client's own server or S3 bucket.
- Notification credentials (Slack and webhook URLs, Telegram bot tokens, webhook signing secrets, and an email-service-provider API key such as Klaviyo) are encrypted at rest with AES-256-GCM and are never returned by the API once saved — the dashboard shows a mask, not the value. They are held by the Platform only; they are not copied to your website.
- Access to the Platform database is restricted to production server infrastructure only — ports are not exposed to the public internet.
- Authentication uses JWT tokens with short expiry (15 minutes) and refresh token rotation.
6. Data Sharing
We do not sell, rent, or share end-user data with third parties for marketing purposes.
Data may be shared only in the following circumstances:
- With the Client — Clients have full access to data collected from their own websites.
- Nobody, for recordings — session recording files are stored by the Platform itself; no third-party storage provider of ours is involved. The one exception is at a Client's own written request: where a Client asks for their recordings to be written to object storage in their OWN cloud account, we configure their site to do that. That storage is the Client's, chosen by the Client and billed to the Client — it is their own infrastructure, not a sub-processor we have engaged, and it is never done on our initiative or for any other Client. Recordings made before the Platform owned storage may still reside on the Client's own server or S3 bucket, which we cannot reach — deleting those files is the Client's own task.
- Notification services — If the Client configures Slack, Telegram, email or webhook notifications, event summaries are sent to those services according to the Client's settings. For a chat, the summary says that a conversation started — the visitor's name and email where the widget collected them, the page, the number of messages and a link to the dashboard — and never contains the transcript, which is read in the dashboard only.
- Chat providers — inbound only — Where the Client connects a chat provider (Brevo Conversations), that provider sends chat transcripts TO the Platform on the Client's configuration. Nothing travels the other way from the Platform: it never sends a message, a visitor or any other data to the provider, and holds no credential for it. The one exception runs inside the visitor's own browser, not through us: where the Client has embedded the provider's widget, the collector hands it the pseudonymous
STOREPILOT_VISITORandSTOREPILOT_SESSIONidentifiers so the transcript can be matched to the visit — only where tracking is allowed, and nothing else. - A model provider of ours — Anthropic writes the daily and weekly digest's narrative, and the summary of a recorded visit, from a statistics sheet the Platform assembles first: counts, revenue totals, page paths, error messages, uptime results and survey scores — and, where you connect a chat provider, the chat itself, so that the morning brief can say what somebody asked about; and what somebody wrote in an enquiry form on your site, shortened, so the brief can say who is waiting for an answer. Never a survey answer a visitor typed, never a visitor or session identifier, never a contact field, never an IP address, and never recording footage. Error messages and page paths are redacted before the sheet is sent, and a chat transcript, like the text of an enquiry, has email addresses, telephone numbers, card numbers and credentials masked on the way — including the visitor's name where we hold one. Of an enquiry the sheet carries whether there is an email or a telephone number to reply on, never the address or the number itself. Anthropic is a sub-processor of ours under the DPA.
- An AI client the Client connects — Where the Client connects an AI client of their own (for example Claude, through the Model Context Protocol), that client reads aggregate statistics, analytics, issues, uptime results, product performance, derived insights, checkout and order records including basket contents and totals, the names and contact details on those records, chat transcripts, survey answers including free text, and a description of a recorded visit — its pages, duration, device and error count, and the narrative summary written about it — together with the pseudonymous visitor and session identifiers that link them. Raw form contents are read only where the connecting person holds the admin role. It never receives a postal address or a postcode — those are refused at collection and a marker is stored in their place — it never receives an IP address, and it never receives session-recording footage: a visit is described and linked, never handed over. It reads only, unless the Client's organization owner has allowed changes from connected AI clients (off by default) and the connecting person allowed changes with their password; even then the only changes it makes are to the notification destinations and uptime monitors of those sites — adding, changing, testing, copying and deleting them as an admin can — with a webhook or Slack destination sending only to a host the owner approved and a monitor checking only the site's own domain, and every owner and admin is told. Access is limited to the sites the Client names when connecting it, and re-checked against their live team membership on every request. The Client disconnects it from Your profile → Connected AI clients → Disconnect, which takes effect immediately. The provider of that client is the Client's sub-processor, not ours. A personal key the Client creates for a script, a server or a header-sending AI client reads the same data under the same refusals and makes the changes above only where the Client created it with changes allowed (a choice that cannot be changed afterwards) and the same owner approval applies; it is limited to the sites or organizations the Client names, created only after the Client re-enters their password, expires after at most 365 days, is stored only as a fingerprint, and is revoked from Your profile → Personal keys → Revoke, which takes effect immediately.
- Our payment processor — Stripe takes payment for paid plans and receives the billing details of the person who subscribes (name, email, billing address, VAT number and payment card). It receives no data about your website's visitors. For those billing details we are the controller, so Stripe is not a sub-processor under the Data Processing Agreement.
- Legal obligations — If required by law, court order, or governmental authority.
7. Data Subject Rights (End-Users of Client Websites)
End-users of Client websites should direct privacy requests to the website owner (the Client), who is responsible for responding as Data Controller. The Platform provides tools to support:
- Right to Access and Portability —
GET /api/v1/sites/:id/visitors/:id/export.jsonreturns everything held about one visitor as a single JSON file: their visitor record, pageviews, leads, recording metadata, clicks and scroll marks, the named events the site sent about them, the automated-traffic verdict on each of their visits with its reasons, session facts, consent decisions, chat transcripts and the faults they encountered. Where the same person used more than one browser, the linked records are listed rather than merged, because a visitor identifier identifies a browser and not a person. Two limits are stated in the file itself: session replay footage is described by its metadata rather than embedded, and error entries are reduced to the fault, because the full record is an aggregate across every visitor who encountered it. - Right to Erasure — Clients can permanently delete all data for a specific visitor using
DELETE /api/v1/sites/:id/visitors/:id/data. This removes pageviews, recordings, leads, clicks, custom events, automated-traffic verdicts, consent records, chat transcripts and rendered page images, and anonymizes linked error records. A transcript is found both by the visitor identifier and by the email addresses their leads carry, so one whose lead has already been erased still goes with them.
8. Storage Used by the Platform Dashboard
The Platform dashboard (used by Clients, not end-users) sets one cookie, to keep you signed in. The short-lived access token is held in localStorage:
| Key | Purpose | Duration |
|---|---|---|
access_token (localStorage) | Authentication JWT | 15 minutes |
sp_refresh (cookie, HttpOnly, SameSite=Strict) | Silent re-authentication; unreadable by page script | 7 days |
These are strictly necessary to keep you signed in and are not used for analytics or advertising.
StorePilot's collectors set one first-party cookie, sp_vid (a browser identifier, two years, renewed on each visit), and duplicate it in localStorage; visit-scoped keys live in sessionStorage. The full list is in the Cookie Policy. The Client is responsible for disclosing this in their cookie notice and, where the law requires it, for obtaining consent first — Settings → Privacy → Require consent before tracking enforces that.
Global Privacy Control is honoured unconditionally on every site, with no setting to disable that. It is honoured in the browser and again on the request: the collectors refuse to send anything when navigator.globalPrivacyControl is set, and the Platform refuses to store anything sent with a Sec-GPC: 1 header — including submissions forwarded server-side by WordPress, where no script of ours is involved. The one exception is the WooCommerce order report described in section 2.3, which is the Client's record of a sale and is stored with a note that the buyer opted out. In California and the other states with universal opt-out laws, Global Privacy Control is treated as a valid opt-out request.
Do Not Track (navigator.doNotTrack, the DNT: 1 header) is not honoured. The W3C discontinued that specification in 2019 and no privacy law names it; browsers that still offer the switch describe it as advisory. Sites that want visitors asked before anything is collected can switch on the consent gate described in the Cookie Policy.
9. Changes to This Policy
We will post any changes to this Privacy Policy on this page and update the "Last updated" date. Material changes are also announced on the Announced Changes page at least 14 days before they take effect.
10. Contact
Data Controller inquiries (Client accounts): contact@store-pilot.net
Data subject inquiries (end-users of Client websites): Contact the website owner directly.