Privacy

What we collect, precisely

This describes what the software does, not what we would like you to believe it does. It is not legal advice, and it does not cover your own obligations for anything else running on your site.

Analytics on this website

getmayfly.com uses Mayfly to measure visits to its public pages, including the demo and the Mayfly House. Login, signup, account recovery, verification, admin and customer dashboard routes are excluded from this website’s analytics. Referrers are reduced to their origin before transmission. The tracker honours the opt-out settings below.

How a visitor is counted

There is no identifier stored on the visitor’s device. Instead, each event is attributed to a hash:

visitor_id = sha256( daily_salt + site_id + ip_address + user_agent )

The salt is random, rotates every day at UTC midnight, and the old value is deleted from the live database once it is two UTC dates old. With the documented 03:00 UTC daily schedule, the maximum live lifetime is about 51 hours. While a salt exists, the corresponding hashes could in principle be worked backwards to an IP address, because IPv4 has only about four billion possibilities. After it leaves the live system, the application can no longer perform that reconstruction. Database backups and write-ahead logs can retain a deleted salt until the infrastructure provider’s backup-retention period expires, so operators must configure that window as part of deployment. The live deletion runs as a scheduled job and the system exposes a metric so a stopped job is noticed.

The honest consequence: a visitor identifier lasts one day. We cannot tell you whether someone came back next week, and we do not offer a report that implies we can.

What is stored

FieldDetail
Page URLQuery strings are stripped by default. Site owners can opt in specific parameters; common identifiers and credential-shaped values are redacted before storage.
Page titleAs reported by the document, with email addresses and bearer-token shapes redacted. Titles are site-controlled content and must not contain personal data.
ReferrerHost only, resolved to a source name. Same-origin referrers are discarded as internal navigation.
UTM parametersOnly if present in the URL.
Country, region, cityDerived from the IP address at request time, then the address is discarded.
Browser, OS, device classParsed from the User-Agent header.
Screen size bucketOne of five breakpoint classes, not the exact dimensions.
Engaged time and scroll depthForegrounded milliseconds and furthest scroll percentage.
Core Web VitalsLCP, INP, CLS, TTFB, FCP, as measured by the browser.
Custom event names and propertiesOnly what the site owner chooses to send. Common identity keys and email/token-shaped values are dropped, but site owners must not send personal data.
Search performanceIf a customer connects Google Search Console, Mayfly imports aggregate query, page, country and device metrics for that customer's verified property.
Customer account dataDashboard accounts use an email address, password hash, membership records and a strictly necessary session cookie. Search Console refresh tokens and queued transactional-email payloads are encrypted at rest.
Early-access waitlistWith your consent, Mayfly stores your email, optional website hostname, signup time and invitation-delivery status in Postgres. These are not analytics events and do not create an account. Only configured, verified operators can read this list or send invitations.

What the tracker does not persist

Customer responsibility

Mayfly is designed for aggregate website measurement, not user profiling. Do not place names, email addresses, account ids, reset links, free-form customer messages or other personal data in tracked URLs, page titles, event names or properties. Server-side guards remove common mistakes, but no heuristic can recognise every possible identifier.

Retention

Waitlist contacts are eligible for removal after 365 days by scheduled maintenance, once any retained invitation-delivery job is removed. Operators can remove a contact earlier on request. Waitlist emails are used only for early-access invitations. Events awaiting recovery after a collector storage failure may be kept in a bounded Postgres queue for up to 24 hours, then removed from that queue on delivery or expiry. Queue status metadata is kept for seven days. This invite-only Postgres beta retains events, Search Console imports and crawl results for 30 days. Daily maintenance removes expired rows at its next run, so deletion can take up to one additional day. Reports do not promise history beyond that window. The collector writes directly to Postgres and does not use the cross-store recovery queue. Queued email ciphertext is erased immediately after delivery, terminal failure or expiry; non-content delivery metadata is removed after seven days. A daily salt remains in the live database for today and the previous UTC date, then is removed by the next scheduled maintenance run (about 51 hours maximum at the documented 03:00 UTC schedule).

Export and deletion

Operators can create a site-scoped export covering account configuration, raw events, aggregates, Search Console rows and crawl results. A separate hard-erasure command first disables collection, deletes the Google credential, removes and verifies every live analytics row, then deletes the site’s control-plane records. Infrastructure backups expire on the operator’s documented provider-retention schedule rather than instantly.

Opting out

The tracker honours the Do Not Track browser setting even though it is widely ignored elsewhere, and it never runs on localhost. Any visitor can exclude themselves permanently on a device by running:

localStorage.setItem('mayfly_ignore', '1')

That flag is read locally and never transmitted.