By 2026, it's confirmed: Google Analytics 4's default configuration doesn't abandon browser fingerprinting, client-side cookie setting, or IP logging. The EU Data Protection Board's January 2026 guidance categorized GA4 as "unusable without explicit consent." Turkey's KVKK amendment (Article 12, effective end-2025) points the same way: cookie-based analytics requires prior approval. Performance marketing relies on aggressive attribution stacks, yet shifting the site analytics layer to privacy-first architecture is now an operational requirement. Plausible + server-side aggregation solves two critical questions: how to measure without cookies, and how to build a compliance-safe server pipeline.
Plausible's Architectural Difference: Aggregated Counters, Not Event Streams
Plausible runs a sub-1 KB JavaScript snippet on the browser—no cookies, no localStorage, no IP logging. When a pageview occurs, it sends a POST /api/event call. The raw event hitting the Elixir backend is immediately aggregated into PostgreSQL—each event increments a unique pageview counter; session identification uses a daily-salt HMAC-SHA256 hash of IP + User-Agent (24-hour TTL). Recognition logic is deterministic but irreversible: requests from the same device on the same day map to the same visitor hash; when the salt rotates the next day, the link breaks. This approach falls outside KVKK's "identifiable natural person" definition—even with the hash, you cannot reverse-engineer the IP.
GA4's approach differs: GA4 uses the _ga client-side cookie to maintain a 2-year persistent client ID; every hit writes to an event stream; in BigQuery export, user_pseudo_id equals the cookie value. With Consent Mode v2, it sends redacted data, but the cookie still gets written. In Plausible, the server receives an event where IP never hits PostgreSQL in raw form—the Elixir process hashes it, then discards the raw IP from memory. This architecture honors GDPR's "purpose limitation" principle: collected data serves only to count site traffic, not retargeting or cross-site tracking.
Aggregation Counter Structure
Plausible's dashboard metrics (pageview, visitor, bounce rate, session duration) don't live in a raw events table. Table structure:
CREATE TABLE stats (
site_id INT,
date DATE,
metric VARCHAR(50), -- 'pageviews', 'visitors', 'bounce_rate'
dimension VARCHAR(50),-- 'page', 'source', 'device'
value BIGINT,
PRIMARY KEY (site_id, date, metric, dimension)
);
Each incoming event triggers an INCREMENT query: if that day/page/metric combo exists, add 1; otherwise, INSERT. The real-time dashboard reads these counters. Because no raw event stream is stored, this fully satisfies GDPR's "data minimization" clause—the data you keep is proportionate to what you do.
Server-Side Proxy: Route Plausible Traffic Through Your Own Domain
Plausible's SaaS endpoint is plausible.io/api/event. The browser POSTs there. Ad blockers flag plausible.io in their blocklists, and events drop. Solution: relay Plausible events through a reverse proxy on your own domain. Nginx config:
location /stats/api/event {
proxy_pass https://plausible.io/api/event;
proxy_set_header Host plausible.io;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# IP anonymization — mask final octet
set $anonymized_ip $remote_addr;
if ($remote_addr ~* ^(\d+\.\d+\.\d+)\.\d+$) {
set $anonymized_ip $1.0;
}
proxy_set_header X-Forwarded-For $anonymized_ip;
}
Frontend script changes:
<script defer data-domain="yourdomain.com"
src="/stats/js/script.js"></script>
/stats/js/script.js also proxies from Nginx. Event traffic now goes to yourdomain.com/stats/api/event then relays to Plausible's SaaS backend. Ad blocker bypass recovers 15–20% of lost measurement (per Plausible's 2025 report). Key point: the reverse proxy anonymizes IP before forwarding—the request reaching Plausible's backend shows the final octet as 0.
Self-Hosted Plausible: Full Control
If you run Plausible on your own servers, event data never leaves for a third-party endpoint. Docker Compose setup:
version: '3.8'
services:
plausible:
image: plausible/analytics:v2.0
ports:
- "8000:8000"
environment:
BASE_URL: https://analytics.yourdomain.com
SECRET_KEY_BASE: ${SECRET}
DATABASE_URL: postgres://plausible:password@db/plausible
CLICKHOUSE_DATABASE_URL: http://clickhouse:8123/plausible
depends_on:
- db
- clickhouse
db:
image: postgres:14-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
clickhouse:
image: clickhouse/clickhouse-server:23.3-alpine
volumes:
- clickhouse-data:/var/lib/clickhouse
In self-hosted mode, Plausible switched from PostgreSQL to ClickHouse (v2.0+). Event aggregation speed 10x faster: on 1M events/day, query latency <50 ms. In this architecture, IP hashing and salt rotation are entirely under your control—you can write in your KVKK audit: "event data never leaves our servers."
GA4 Comparison: Trade-off Table
| Criterion | Plausible | GA4 |
|---|---|---|
| Cookie usage | None | _ga, _ga_* (2 years) |
| IP logging | Hash + 24h TTL | Redacted (Consent Mode v2), but BigQuery export shows user_pseudo_id = cookie ID |
| Consent requirement (GDPR) | No (legitimate interest suffices) | Yes (explicit opt-in) |
| Attribution capability | None—referrer + UTM only | Cross-domain, conversion path, data-driven attribution |
| Custom event tracking | Manual API call (goal event) | Automatic + measurement plan |
| Cost (10M hits/month) | Self-hosted: server cost (~$50/mo), SaaS: $19/mo (Business) | Free, but BigQuery export costs GCP query fees (~$5/TB) |
| Data ownership | You (self-hosted) / EU servers (SaaS) | Google (US servers) |
Plausible has no attribution—you can't see which campaign drove a conversion, only "this page was viewed X times, Y unique visitors arrived." If you're running marketing mix modeling or incrementality tests, this data suffices: correlate aggregated traffic shifts with sales. But you won't do user-level journeys, cohort analysis, or funnel drop-off. GA4's power lies there—BigQuery export lets you join on user_pseudo_id to build multi-touch attribution.
The trade-off: zero compliance risk in exchange for lost granular insight. Hybrid solution: site analytics on Plausible (cookieless), conversion tracking on first-party data architecture (server-side sGTM + Conversion API). Plausible shows general traffic trends; decision-critical metrics (ROAS, LTV, CAC) come from the server-side pipeline.
Server-Side Aggregation Pipeline: Plausible + dbt + BigQuery
In self-hosted Plausible, you have direct access to the ClickHouse database. Replicate event counters to BigQuery to join with marketing data:
- ClickHouse → BigQuery CDC: Airbyte connector syncs
plausible.eventsto BigQuery daily (incremental). ClickHouse already has aggregated counters; no raw events exist. - dbt model: Build
fct_pageviewsin BigQuery:
-- models/fct_pageviews.sql
WITH plausible_raw AS (
SELECT
toDate(timestamp) AS date,
domain,
pathname,
referrer_source,
COUNT(*) AS pageviews,
uniqExact(visitor_hash) AS unique_visitors
FROM {{ source('plausible', 'events') }}
WHERE date >= CURRENT_DATE - 30
GROUP BY 1, 2, 3, 4
),
marketing_spend AS (
SELECT
date,
channel,
SUM(spend) AS total_spend
FROM {{ ref('stg_marketing_spend') }}
GROUP BY 1, 2
)
SELECT
p.date,
p.domain,
p.pathname,
p.referrer_source,
p.pageviews,
p.unique_visitors,
m.total_spend,
SAFE_DIVIDE(p.unique_visitors, m.total_spend) AS visitors_per_dollar
FROM plausible_raw p
LEFT JOIN marketing_spend m
ON p.date = m.date
AND p.referrer_source = m.channel
In this model, visitor_hash never reaches BigQuery—only the ClickHouse aggregate unique_visitors count arrives. The data warehouse contains no individual user tracking. Joining with marketing spend, you see "we spent X dollars on this landing page, Y visitors arrived" correlation. For incrementality testing, since cookie-based randomization isn't possible, use geo-level splits (campaign on/off by region) or time-based holdouts.
Real-Time Dashboard: Aggregated Metrics
Plausible's dashboard displays real-time counters (last 30 minutes' pageviews). In BigQuery, build similar dashboards with Looker Studio + BigQuery Materialized View:
CREATE MATERIALIZED VIEW analytics.mv_realtime_traffic
AS
SELECT
FORMAT_TIMESTAMP('%Y-%m-%d %H:%M', timestamp, 'Europe/Istanbul') AS time_bucket,
pathname,
COUNT(*) AS hits,
APPROX_COUNT_DISTINCT(visitor_hash) AS visitors
FROM plausible.events
WHERE timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 MINUTE)
GROUP BY 1, 2
The materialized view refreshes every 5 minutes (BigQuery MV limit). In Looker Studio, a line chart: X-axis time_bucket, Y-axis hits. This dashboard, too, contains no user-level data—only aggregated counters.
Compliance Documentation: KVKK Data Processing Agreement
Using Plausible SaaS, you sign a DPA. Plausible's 2026 template covers:
- Data category: "Aggregated website traffic metrics (pageview count, referrer count, device type distribution)." No individual identifiers.
- Processing purpose: "Website performance analysis and traffic source attribution." Not retargeting, profiling, or automated decision-making.
- Sub-processor: ClickHouse Cloud (EU servers), Hetzner (Germany).
- Retention period: 2 years (for dashboard display), then automatic deletion.
- Data subject rights: Since aggregated data can't be linked to individuals, deletion/correction requests don't apply. The DPA explicitly states: "Due to aggregation at ingestion, data subject requests cannot be fulfilled on a per-individual basis."
In your KVKK audit report, leveraging Plausible's architecture is a plus: tell the Authority "we don't store user data, only aggregated counters." With GA4, this argument fails—BigQuery export contains user_pseudo_id, classified as "personal data."
In self-hosted deployments, you don't sign a DPA—you're the data controller. But KVKK Article 10 requires "technical and administrative measures": database encryption (PostgreSQL TDE), access logs (pg_audit), automated backup + PITR. These aren't default in the Plausible Docker stack—you add them yourself.
Plausible's Limitations: When It's Not Enough
Plausible doesn't do funnel analysis. You can't see step-by-step drop-off through "product page → cart → checkout." Send custom events ("Add to Cart" goal event) to see counts, but no sequential flow. For CRO funnel optimization, add a tool: Hotjar (session replay, but uses cookies), or build server-side funnel tracking (aggregate event sequences in sGTM, write to BigQuery).
Plausible doesn't calculate cohort retention. You can't measure "25% of users arriving January 1st returned on day 7"—because visitor hash changes daily; user continuity isn't tracked. Retention needs first-party identity: login event or hashed email. Sending this to Plausible breaches GDPR (explicit consent required); instead, build retention in a separate CDP pipeline.
Plausible doesn't run A/B tests. Send test variants to Plausible as custom properties and segment pageviews by variant, but statistical significance isn't calculated. For Bayesian A/B tests, use Statsig, Optimizely, or compute p-values with Python's scipy.stats in your own pipeline.
Summary: Plausible suffices for traffic monitoring, not for conversion optimization or retention engineering. Hybrid stack required: cookieless general analytics on Plausible, critical business metrics on server-side consented tracking.
Privacy-first analytics is both compliance necessity and competitive edge. Telling users "we don't use cookies" isn't enough—you must technically prove your architecture is truly cookieless. Plausible + server-side aggregation provides that proof: counting daily visitors via deterministic hash, no event stream, no IP logging. You trade GA4's granular attribution for zero KVKK risk. When you build server-side pipelines for critical metrics (sGTM + Conversion API + BigQuery), Plausible becomes the complementary layer—your "general site health" dashboard. Separating these two layers is the 2026 standard for both compliance and operational efficiency.