The LinkedIn version of this story is "we went privacy-first". The internal version is usually uglier: the Monday traffic chart no longer matches Search Console, paid, or the application database, and nobody can explain the gap without a twenty-minute lecture on Consent Mode.
Teams do not leave Google Analytics 4 because a blog called it unethical. They leave because a cookie-gated tracker is a poor instrument once a large slice of visitors clicks "reject". SiteLine's pitch is narrower than a manifesto: cookieless page analytics so the on-site series is complete, plus Search Console so organic is not a GA4 channel guess, plus two read-only MCP servers so an agent can ask the same questions without a screenshot. The privacy model is a product constraint, not a slogan. Chris Richards builds SiteLine at Aglet Technologies. The operator contact is [email protected], and /trust is the public page for who that is.
Consent rate is a measurement failure
GA4's default identity is a first-party cookie. In the EEA, that almost always means a banner, a CMP, and Consent Mode wiring. Reject analytics cookies and those hits never become the events you report. Modelled conversions try to fill the hole. They are a statistical story, not a count you can reconcile to /signup.
Google's introduction to GA4 lists privacy controls that include cookieless measurement and behavioral and key event modeling, next to direct integrations with media platforms. That sentence is easy to quote in a migration doc as if the tag had stopped using cookies. It has not, in the ordinary web setup. Cookieless measurement and modeling are how GA4 talks about the observations it does not have. The observations it does have still ride a client id. The people who click Reject are missing from the event stream you chart. The people who click Accept are a biased remainder: more likely to be logged in, more likely to already trust the site, more likely to finish the task they came for. Marketing then optimizes for that remainder and calls it the audience. This page will not invent a consent percentage to decorate that sentence. The direction of the bias is the point. The size of the bias is yours to measure in your CMP, not mine to fabricate.
Cookieless tracking does not make you exempt from privacy law. It removes the cookie as the reason this particular tracker needs a banner. SiteLine does not set a first-party analytics cookie. Collect uses fetch with credentials: 'omit'. Visitors are a SHA-256 of truncated IP (IPv4 /24, IPv6 /48), user agent, and a daily rotating salt that resets at UTC midnight. The raw IP is not stored on the event. You still need a privacy notice, and you still own whatever else you load: pixels, session replay, chat widgets. See GA4 and the cookie banner and unique visitors without cookies. The public notice for this product is /privacy.
What "complete" means here is specific. The script sees browsers that executed it. It does not see people who blocked the script. It does not see a person across two UTC days. It does see the visitor who rejected a CMP and left the script running. That single inclusion is why Monday's on-site series can move with the application database again, while GA4 users stay pegged to the accept cohort.
The UI became a specialist tax
Universal Analytics was clumsy. GA4 is a product designed around an event schema, Explorations, and Google Ads. For a five-person SaaS marketing team, "create a comparison in Explorations" is a weekly tax. Thresholding when Google signals is on, and sampled Explorations, mean the screenshot in the board deck is not the same query you ran yesterday.
Google's GA4 sampling page states the quota in events, not in a vibe. Standard properties sample event-level queries above 10 million events. Analytics 360 goes up to 1 billion, and starts from a default of 100 million events per query so the answer returns faster. Explore can ask for more detailed results. The data-quality icon shows the percentage of data used to build the result. Unsampled user and session counts are still estimates, via HyperLogLog++, and Google says the discrepancy is under 1% in most cases and can be higher when several of those metrics are combined. A board slide that hides the icon is a different report from the one the analyst saw.
Universal Analytics had its own sampling article, with thresholds counted in sessions. Standard Universal Analytics properties stopped processing new hits on 1 July 2023. A current GA4 property follows the event quotas above. A comparison that still describes GA4 sampling in session ceilings is describing the retired product.
SiteLine's on-site reports are the boring set: pages, referrers, countries, devices, browsers, OS, UTMs, goals, funnels, live view. Goals are rules on paths and event names you already send — exact path, path contains, or event name — not extra billable events. On-site events are not sampled. Starter and Growth apply a soft cap: ingest continues, and charts hide overflow until you upgrade. That is a visibility rule you can see, not a scaled sample with a percentage in the corner. If you need a specialist to build the weekly report, the tool is part of the cost.
Ads coupling is a feature until it is not
GA4 is excellent if the point of the website is Google Ads. Conversion export, audiences, and the rest of the Google stack are why the product is free. The moment your acquisition is mostly organic, partner, or product-led, you are paying for that coupling in complexity and in a processor you may not want on the marketing site.
Leaving GA4 does not require leaving Google Search Console. SiteLine asks for webmasters.readonly only. It cannot submit sitemaps, request indexing, or change users. Backfill is 16 months of whatever Google still holds in the rolling Performance window. A refresh every 4 hours reimports the last 7 days, including fresh rows. Recent days include fresh data and can still change until Google finalizes them. Google's own retrieval guide tells API users to query a single day, notes that data is typically available after 2–3 days, and caps exposure at 50,000 rows per day per search type. SiteLine follows the daily shape and then keeps re-reading the last week so fresh rows are included. Unlimited sites. That is the organic source of truth, sitting next to cookieless pageviews instead of being filtered through a session channel.
Clicks are not sessions. Do not average CTR or position across query rows. CTR is a fraction of 1: a value of 0.0412 is 4.12%, not 4.12 already. Query rows do not sum to the site total, because anonymized queries stay in the chart and because of row caps. The human version of that warning is Search Console clicks vs analytics sessions.
What leaving actually costs
| Cost | If you stay on GA4 | If you move the marketing site |
|---|---|---|
| Measurement bias | Consent-gated cookies; modelled gaps | Cookieless series; still no cross-day person ID |
| Specialist time | Explorations, thresholds, schema | Fewer reports; two read-only MCP servers for Claude, ChatGPT, Cursor |
| Organic queries | Separate Search Console UI, 1,000-row export, rolling 16-month window | Imported 25,000 rows/day/report, kept while subscribed |
| Money | $0 licence, CMP and engineering time | From $4.99/mo after a 7-day trial, no card to start |
| What you give up | Nothing of the Google ads graph, if you stay | Ads attribution, BigQuery, replay, heatmaps, user identity across days |
Migration is not a warehouse move. You will not get GA4's historical user IDs into a cookieless tool, and you should not try. Run both for a month. Compare pageviews to Search Console clicks on the same URLs. They will not match, and they should not: clicks are searches that led to a click, pageviews are visits that executed the script. What you want is a stable relationship, not identical totals.
For SaaS specifically, the failure mode is using GA4 as a product-analytics stand-in. That story is GA4 for SaaS. For the identity mechanics, cookieless vs GA4. Direct vendor grid: SiteLine vs Google Analytics. Peers that are already cookieless, and why Search Console is the column that matters, are in the privacy-first analytics comparison.
Worked example: the Monday export that is not the chart
Labeled hypothetical. Not a customer. Not a consent-rate study. The figures are row caps, not a traffic result.
Monday morning someone exports the Performance report for the previous Tuesday, queries dimension, web search. The file has 1,000 rows. Google's export help says that is the product: the download is truncated to 1,000 representative rows. For a smaller site that may already be most or all of the named queries. For a larger site it is a greatest-hits list. The chart total on the same report is not the sum of those 1,000 rows. Google says the totals shown are the actual totals, not totals with the row limit applied. The deep dive on performance data explains the two reasons the sums diverge. Anonymized queries (rare queries, withheld) are in the chart unless you filter by query, and they have no row. Separately, the UI will not export more than 1,000 rows, while the API can expose up to 50,000 rows per day per site per search type. rowLimit pages that API at 25,000.
SiteLine's import for that Tuesday query report holds 25,000 rows. The UI export holds 1,000. 24,000 query rows never appear in the export the team pasted into the deck. They also never appear in GA4, because GA4 does not have the query table. The organic channel in GA4 is a session label. It cannot list the tail.
If your property already fits in 1,000 query rows, this hypothetical is not your outage. Say so. Google expects the row limit to leave most properties untouched. The reason a small site still leaves the Search Console UI is the other cliff: days age out of the rolling 16-month Performance window. SiteLine keeps imported days while you are subscribed. That limit has its own page, Search Console's 16-month limit, and the 1,000-row ceiling has its own page too.
What Monday should compare, once both series exist:
| Series | Unit | Fair question |
|---|---|---|
| GA4 users | Consented cookie, possibly sampled in an Exploration | Did the accept cohort move? |
| SiteLine daily hashes | Truncated IP + user agent + daily salt, reset UTC midnight | Did the script see more visitors today? |
| Search Console chart clicks | Property total for that search type, including anonymized queries | Did Google send more clicks? |
| Sum of imported query rows | Named queries only, at most 25,000 | Of the queries we can see, which moved? |
An agent with both MCP servers can ask the last two without the export. It still has to be told not to subtract visitors from clicks. Setup context is SEO analytics for AI agents.
What you install, and what you pay
Install is a deferred script at /js/script.js posting to POST /api/analytics/event, or @siteline.tools/tracker / @siteline.tools/react. A first-party proxy is yours to configure if ad blockers eat the default origin. SiteLine does not manage CNAMEs in v1. Hostname allowlist rejects events from hosts you did not name. Known bots are dropped before they count against quota.
Plans: Starter $4.99 for 1 million events, Growth $19.99 for 10 million, Scale $99.99 and then $2.99 per extra million. MCP is included, not an add-on. Trial: 7 days, no card to start, visibility about 50,000 events. Soft cap on Starter and Growth hides overflow in charts while ingest continues. After access ends, analytics has a 30-day grace period. Signup: /register. Policy: /privacy. Billing rules: /docs/billing.
A practical cutover, in order:
- Keep GA4 read-only if Ads or an old Exploration still matters. Do not try to import client ids.
- Allowlist the marketing hostnames and ship the script. Confirm a pageview lands without a SiteLine analytics cookie.
- Connect Search Console read-only and wait until the backfill's coverage dates are honest.
- For a month, chart SiteLine uniques and Search Console clicks on the same URLs. Expect them to differ. Investigate a break in the relationship, not a hunt for equal totals.
- Only then decide whether the GA4 tag on the marketing site is still earning its CMP cost.
FAQ
Will our historical GA4 users map across?
No. SiteLine's visitor hash is daily and cookieless. There is no user-level identity across days, and no import of GA4 client IDs. Treat the cutover as a new series. Keep GA4 read-only if you still need old explorations.
Do we lose Google Ads conversion import?
If you leave GA4, yes. SiteLine does not do Ads attribution. Keep a GA4 property, or the Ads tag, for paid if that channel matters. Use SiteLine for the public site and Search Console, not as an Ads replacement.
Is this only for EU traffic?
No. Consent banners are most painful in the EEA, but cookie-gated analytics is a biased sample anywhere a CMP is shown. Cookieless tracking is also simpler to explain in a privacy notice even when a banner is not required. The hash is still often personal data. "No analytics cookie" is not "outside privacy law".
Why does the Search Console export disagree with the chart?
Because the export is at most 1,000 representative rows, and because anonymized queries can be inside the chart total without a row. Google's export help says the totals are the actual totals, not the truncated sum. Summing the CSV and calling the gap a tracking bug is the Monday meeting this page is about.