webtracking.org
platforms

Snowplow: the schema-first event pipeline you run yourself

How Snowplow works end to end — trackers, collector, enrichment, and warehouse loaders — why Iglu schemas come before instrumentation, and what warehouse-native modeling means for the team that owns it.

last verified 2026-07-11

Snowplow inverts the usual analytics bargain. Instead of sending events to a vendor who returns dashboards, you run the pipeline — in your own cloud account — and the product is the data itself: schema-validated, event-level, landing raw in your warehouse. There is no reporting UI to fall back on, which is either the whole point or a disqualifier, depending on your team. The directory entry has the summary and alternatives, and the privacy scorecard grades its data posture; this guide covers how the pipeline actually works and what owning it entails.

Pipeline anatomy

A Snowplow deployment is a chain of discrete services, each replaceable and each observable:

  1. Trackers — SDKs for web (JavaScript), mobile, and a long tail of server languages emit events to your collector endpoint. The web tracker is deployed on your own subdomain (sp.yourdomain.com), so collection is genuinely first-party: the collector sets its identifier in a server-set first-party cookie, which survives browser tracking-prevention measures that cap script-writable storage, and requests to your own domain are not on generic blocklists the way vendor endpoints are.
  2. Collector — a stateless HTTP service that writes raw payloads to a stream (Kinesis on AWS, Pub/Sub on GCP, Kafka where you bring your own).
  3. Enrich — consumes the raw stream, validates every event against its schema, runs enrichments, and emits enriched events — or routes failures to a dedicated failed-events stream. Nothing is silently dropped; a malformed event is data about your instrumentation.
  4. Loaders — land enriched events in BigQuery, Snowflake, Databricks, or Redshift (and/or a lake), typically within seconds to minutes.

Every stage is infrastructure you monitor like any other production system: stream lag, enrich throughput, loader failures. That is the honest cost of the architecture. The Community Edition is free to run (you pay cloud costs); Snowplow’s managed offering runs the same pipeline in your account for a fee — and note that recent core pipeline releases ship under the source-available Snowplow Limited Use License rather than Apache 2.0, which matters if your standardization story assumed a permissive fork path.

Schemas first: Iglu

The defining design decision: every event and entity is self-describing JSON, validated against a registered schema before it is accepted. Schemas live in an Iglu registry — a versioned schema repository the pipeline resolves against — and are referenced by URI:

{
  "$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
  "self": {
    "vendor": "com.acme",
    "name": "add_to_cart",
    "format": "jsonschema",
    "version": "1-0-2"
  },
  "type": "object",
  "properties": {
    "sku":      { "type": "string", "maxLength": 64 },
    "quantity": { "type": "integer", "minimum": 1 },
    "value":    { "type": "number", "minimum": 0 }
  },
  "required": ["sku", "quantity", "value"],
  "additionalProperties": false
}

Tracking code then references the schema explicitly:

window.snowplow('trackSelfDescribingEvent', {
  event: {
    schema: 'iglu:com.acme/add_to_cart/jsonschema/1-0-2',
    data: { sku: 'WP-1', quantity: 1, value: 49.0 }
  }
});

Versioning uses SchemaVer (MODEL-REVISION-ADDITION): an ADDITION (new optional field) is non-breaking; a MODEL bump signals consumers must change. Because validation happens in the pipeline, the tracking-plan-as-enforced-contract pattern that other stacks bolt on with CI scripts is simply how Snowplow works — an event that violates its schema never reaches the warehouse; it lands in the failed-events stream with the validation error attached, where you alert on it.

The second half of the model is entities (historically “contexts”): independently-schema’d objects — a user, a product, an A/B test assignment, a page — attached to any event. Instead of denormalizing product fields into every commerce event, you define a product entity once and attach it wherever relevant. Entities are how Snowplow keeps a wide event vocabulary out of a combinatorial schema explosion.

Enrichment

Between validation and loading, Enrich runs a configurable series of enrichments per event:

  • Reference lookups — IP → geolocation, useragent parsing, referer classification, marketing campaign attribution from URL parameters (which expects disciplined links — the UTM standard upstream pays off here).
  • Hygiene and privacy — the IAB bots & spiders enrichment, and the PII pseudonymization enrichment, which hashes or redacts configured fields in the pipeline, so raw identifiers need never land in the warehouse at all. For teams whose privacy posture drives the Snowplow decision, this stage is the argument.
  • Custom logic — a JavaScript enrichment for arbitrary per-event transforms, plus API- and SQL-lookup enrichments for joining external reference data at collection time.

Enrichment is where Snowplow differs most from “raw hits to a bucket” pipelines: the events arrive in the warehouse already validated, classified, and privacy-filtered, with the logic version-controlled in pipeline configuration rather than scattered across downstream SQL.

Warehouse-native modeling

On BigQuery, Snowflake, and Databricks, enriched events land in a single wide table (atomic.events) — one row per event, with self-describing event and entity payloads in typed nested columns alongside 100+ standard fields. (Redshift, lacking those nested types, historically shreds self-describing events and entities into side tables joined back to atomic.events.) This is deliberately unopinionated: there are no sessions, users, or funnels in the data as landed, because those are modeling decisions, and Snowplow’s position is that they belong downstream where they are inspectable and re-runnable.

In practice, downstream means dbt: Snowplow maintains dbt packages that incrementally derive page-view, session, and user tables from the atomic stream, with configurable session timeouts and identity logic. Everything the sessionization guide says about warehouse sessionization — retroactive definitions, transparent rules, reconcilable numbers — applies natively here, because there is no vendor-computed session to disagree with. Your BI layer, experimentation analysis, and attribution modeling all sit on tables whose lineage you can read, in BigQuery, Snowflake, or ClickHouse-style engines via the lake.

Who should run it

The honest fit assessment:

Snowplow earns its keep when behavioral data is a first-class asset — you have data engineers, a warehouse at the center of your stack, schema governance you intend to enforce, event volumes or privacy requirements that make vendor pipelines uncomfortable, and consumers (ML features, personalization, finance-grade reporting) that need event-level fidelity rather than aggregates.

It is the wrong tool when the organization needs dashboards out of the box, nobody owns infrastructure, or the real requirement is “GA4, but nicer.” Running collector + enrich + loader plus a dbt project to answer “how many sessions yesterday” is engineering spend without return at small scale — a managed product analytics tool or PostHog-class platform answers faster. And if the appeal is specifically “instrument once, route to marketing tools,” that is a CDP-shaped problem — compare Segment and RudderStack — not a pipeline-shaped one.

The deciding question is ownership: Snowplow gives you the entire chain from beacon to modeled table, on the condition that you staff it. Teams that want that trade rarely go back; teams that did not know they were signing up for it rarely make it past the first quarter.