# Privacy

This page describes the data this site collects about your visit, why, and how to ask for it to be removed.

## What we collect

When you load a property listing page, a small first-party script (`/v.js`) records:

Field | Why | Stored as
--- | --- | ---
Page URL, page title, referrer | So we know which listings get visitors and where they came from. | `:PageView` node
Visitor ID (random, browser-local) | So we can tell two visits from one device apart from two devices. | `:AnonVisitor` node (anonymous), or linked to a `:Person` if you arrived via a personalised marketing link.
Session ID (random, per tab) | So one tab's activity stays together. | `:Session` node
Clicks on tagged elements (gallery, floorplan, etc.) | So we know which parts of a listing get interaction. | `:Click` node
Scroll depth — 25%, 50%, 75%, 100% | So we know how far you read. | `:ScrollMilestone` node (one per page view, max depth recorded)
Time spent on a page (dwell) | Same. | Property of the `:PageView` node

We do not collect: cursor positions, keystrokes, form contents, screen recordings, or anything from third-party tracking networks. The pixel is loaded from the same site as the listing, never from a third party.

## Cookies and storage

Before any of the storage below is used, you see a consent banner and choose to accept or reject. If you reject, nothing in the second table is ever written. The only cookie that is set without consent is the one that remembers your consent decision — this is permitted under PECR Regulation 6(4) as strictly necessary to deliver the consent service you asked for.

Set even when you reject (strictly necessary):

Key | Type | Purpose | Lifetime
--- | --- | --- | ---
`mxy_consent` | Cookie (`SameSite=Lax`, `Secure`) | Remembers whether you accepted or rejected, so the banner doesn't re-show on every page. | 12 months

Set only after you accept:

Key | Type | Purpose | Lifetime
--- | --- | --- | ---
`mxy_v` | Cookie (`HttpOnly`, `SameSite=Lax`, `Secure`) | Signed token containing your contact identifier — only set if you arrived via a personalised marketing link. Lets the site recognise you on later visits without you clicking the link again. | 30 days
`mxy_visitor_id` | localStorage | Random ID so we can tell two visits from one browser apart from two browsers. | Until you clear browser storage
`mxy_session_id` | sessionStorage | Random ID so one tab's activity stays grouped together. | Until you close the tab
`mxy_session_pv` | sessionStorage | Page-view identifier used to roll scroll milestones up into a single record per page. | Until you close the tab
`mxy_last_pv` | sessionStorage | Deduplicates a single page view across very fast client-side navigations (within 5 seconds). | Until you close the tab
`mxy_scroll_depth` | sessionStorage | Highest scroll milestone already recorded for the current page, so we only send each one once. | Until you close the tab
`mxy_dwell_start` | sessionStorage | Time you arrived on the page, used to compute dwell when you navigate away. | Until you close the tab

## Withdrawing consent

To change your mind after accepting or rejecting, click Manage cookies in the page footer. The banner re-opens and you can switch your choice. If you flip from accept to reject, every key in the second table is cleared from your browser immediately. The personalised cookie (`mxy_v`) is cleared by your browser when it next sees a response that overrides it; if you want it removed sooner, clear cookies for this site in your browser settings.

Withdrawing consent stops new visit data from being written. It does not delete visit data already on our servers from your previous accepted sessions. For that, see “Right to access and erasure” below.

## Cross-session attribution

If you visit anonymously today and later click a personalised marketing link from the agent, prior anonymous visits from the same browser are linked to your contact record. This is the only way an anonymous visit ever becomes named.

## Retention

Visit data is kept until you ask us to remove it. There is no automatic time-based deletion. If you want your data removed, see the next section.

## Right to access and erasure

To see what we hold or to ask for it to be removed, contact the agent. We honour GDPR Article 15 (access) and Article 17 (erasure). Erasure cascades: removing your contact removes every session, page view, click, and scroll milestone tied to your identity. Anonymous page views from browsers we cannot link to you cannot be erased individually, because there is nothing identifying you to match them against.

## Bots and crawlers

Search engines and link checkers are filtered out by user-agent before any data is written. They are also excluded from rate-limit budgets so legitimate visitors are never blocked because a crawler hammered the endpoint.

## This page

This is a static description. The behaviour above is implemented in `platform/ui/server/routes/visitor-event.ts` and `platform/ui/public/v.js`. The schema is declared in `platform/neo4j/schema.cypher` under the Visitor Graph section.