Skip to main content

Snowplow

Web Source code Package

Snowplow is a behavioral data platform for collecting and routing event data. The destination sends events via the browser tracker, supporting both the npm @snowplow/browser-tracker and the JavaScript tracker (sp.js). walkerOS handles tracker initialization, plugin loading, activity tracking (page pings), and self-describing ecommerce events with context entities.

Where this fits

Snowplow is a web destination in the walkerOS flow:

Installation

npm install @walkeros/web-destination-snowplow

The destination supports two tracking approaches:

  • JavaScript tag (sp.js): loads the Snowplow tracker script from CDN
  • npm packages: uses @snowplow/browser-tracker for smaller bundles and tree-shaking

Loads the Snowplow tracker script automatically. Simple setup, works everywhere.

import { startFlow } from '@walkeros/collector';
import { destinationSnowplow } from '@walkeros/web-destination-snowplow';

const { elb } = await startFlow({
destinations: {
  snowplow: {
    code: destinationSnowplow,
    config: {
      settings: {
        collectorUrl: 'https://collector.example.com',
        appId: 'my-app',
      },
      loadScript: true,
    },
  },
},
});

See bundled mode setup | CLI reference

Configuration

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.

Settings

PropertyTypeDescriptionMore
collectorUrlstringSnowplow collector endpoint URL
appIdstringApplication identifier
trackerNamestringTracker instance name
platformstringPlatform identifier
pageViewTrackingbooleanEnable automatic page view tracking
snowplowsnowplowSnowplow-specific ecommerce configuration
actionSchemastringEcommerce action schema URI
productSchemastringProduct entity schema URI
cartSchemastringCart entity schema URI
transactionSchemastringTransaction entity schema URI
refundSchemastringRefund entity schema URI
checkoutStepSchemastringCheckout step entity schema URI
promotionSchemastringPromotion entity schema URI
userSchemastringUser entity schema URI
customSchemasRecord<string, string>Custom entity schemas
currencystringDefault currency code (ISO 4217)
discoverRootDomainbooleanDiscover root domain for cookies
cookieSameSite'Strict' | 'Lax' | 'None'Cookie SameSite attribute
appVersionstringApplication version
contextscontextsBuilt-in context entities
webPagebooleanWeb page context
sessionbooleanClient session context - enables client_session schema
performanceTimingbooleanPerformance timing context
geolocationbooleanGeolocation context
anonymousTrackingboolean | objectEnable anonymous tracking (no user identifiers)
pluginsArray<any>Snowplow plugins
activityTrackingactivityTrackingPage ping configuration
minimumVisitLength*numberSeconds before first ping
heartbeatDelay*numberSeconds between pings
globalContextsArray<any>Global context entities
* Required fields

Mapping

Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

PropertyTypeDescriptionMore
contextArray<object>Context entities to attach to this event
snowplowsnowplowSnowplow-specific settings override
actionSchemastringOverride action schema for this specific event

Examples

Add to cart

A product add fires a Snowplow ecommerce add_to_cart action with product, cart, page, and user contexts.

Event
{
  "name": "product add",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420
  },
  "context": {
    "shopping": [
      "intent",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "2a75c2e594f12c45",
  "trigger": "click",
  "entity": "product",
  "action": "add",
  "timestamp": 1700000401,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "add_to_cart",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
        "data": {
          "id": "data.id",
          "name": "data.name",
          "category": "data.category",
          "price": "data.price",
          "currency": {
            "key": "data.currency",
            "value": "USD"
          },
          "quantity": {
            "key": "data.quantity",
            "value": 1
          }
        }
      },
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/cart/jsonschema/1-0-0",
        "data": {
          "total_value": "globals.cart_value",
          "currency": {
            "key": "globals.cart_currency",
            "value": "USD"
          }
        }
      },
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/page/jsonschema/1-0-0",
        "data": {
          "type": "globals.page_type",
          "language": "globals.language"
        }
      },
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/user/jsonschema/1-0-0",
        "data": {
          "id": "user.id",
          "email": "user.email",
          "is_guest": {
            "fn": {
              "$code": "e=>{var o;return!!(null==(o=e.user)?void 0:o.id)||void 0}"
            }
          }
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "add_to_cart"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "price": 420,
        "currency": "USD",
        "quantity": 1
      }
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/cart/jsonschema/1-0-0",
      "data": {
        "currency": "USD"
      }
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/page/jsonschema/1-0-0",
      "data": {}
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/user/jsonschema/1-0-0",
      "data": {
        "id": "us3r",
        "is_guest": true
      }
    }
  ]
})

Checkout step

A checkout view fires a Snowplow checkout_step action with the current step and option.

Event
{
  "name": "checkout view",
  "data": {
    "step": "payment",
    "currency": "EUR",
    "value": 462
  },
  "context": {
    "shopping": [
      "checkout",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "checkout",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "checkout",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "e57f61054231a29f",
  "trigger": "load",
  "entity": "checkout",
  "action": "view",
  "timestamp": 1700000405,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "checkout_step",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/checkout_step/jsonschema/1-0-0",
        "data": {
          "step": "data.step",
          "option": "data.option"
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "checkout_step"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/checkout_step/jsonschema/1-0-0",
      "data": {
        "step": "payment"
      }
    }
  ]
})

Transaction with products

A transaction event adds one Snowplow product context per nested product via a loop mapping.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "19d3a0bba4401b0b",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000407,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "transaction",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/transaction/jsonschema/1-0-0",
        "data": {
          "transaction_id": "data.id",
          "revenue": "data.total",
          "currency": "data.currency"
        }
      },
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
        "data": {
          "loop": [
            "nested",
            {
              "map": {
                "id": "data.id",
                "name": "data.name",
                "price": "data.price"
              }
            }
          ]
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "transaction"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/transaction/jsonschema/1-0-0",
      "data": {
        "transaction_id": "0rd3r1d",
        "revenue": 555,
        "currency": "EUR"
      }
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "price": 420
      }
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "price": 42
      }
    },
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
      "data": {
        "name": "Surprise"
      }
    }
  ]
})

Initialization

Destination bootstrap creates a Snowplow tracker pointed at the configured collector URL.

Event
{
  "loadScript": true,
  "settings": {
    "collectorUrl": "https://collector.example.com",
    "appId": "my-app",
    "pageViewEvent": "page view"
  }
}
Out
snowplow.newTracker("sp", "https://collector.example.com", {
  "appId": "my-app",
  "platform": "web"
})

Page view

A page view calls Snowplow trackPageView directly instead of a self-describing event.

Event
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "47d9ef7ad12b267f",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000404,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Out
snowplow.trackPageView()

Product view

A product view fires a Snowplow ecommerce action with a product context schema and pricing fields.

Event
{
  "name": "product view",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420
  },
  "context": {
    "shopping": [
      "detail",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "fa91345c7cde6711",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000400,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "product_view",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
        "data": {
          "id": "data.id",
          "name": "data.name",
          "category": "data.category",
          "price": "data.price",
          "currency": {
            "key": "data.currency",
            "value": "USD"
          },
          "brand": "data.brand",
          "variant": "data.variant"
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "product_view"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/product/jsonschema/1-0-0",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "price": 420,
        "currency": "USD"
      }
    }
  ]
})

Promo view

A promotion visible event fires a Snowplow promo_view action with a promotion context.

Event
{
  "name": "promotion visible",
  "data": {
    "name": "Setting up tracking easily",
    "position": "hero"
  },
  "context": {
    "ab_test": [
      "engagement",
      0
    ]
  },
  "globals": {
    "pagegroup": "homepage"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "4e53223beacdbb44",
  "trigger": "visible",
  "entity": "promotion",
  "action": "visible",
  "timestamp": 1700000403,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "promo_view",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/promotion/jsonschema/1-0-0",
        "data": {
          "id": "data.id",
          "name": "data.name",
          "creative_id": "data.creative_id",
          "type": "data.type",
          "position": "data.position",
          "slot": "data.slot"
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "promo_view"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/promotion/jsonschema/1-0-0",
      "data": {
        "name": "Setting up tracking easily",
        "position": "hero"
      }
    }
  ]
})

Struct event

A custom event is tracked via Snowplow trackStructEvent with category, action, label, property, and value.

Event
{
  "name": "product visible",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420,
    "position": 3,
    "promo": true
  },
  "context": {
    "shopping": [
      "discover",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "2c1e11229f58dff7",
  "trigger": "load",
  "entity": "product",
  "action": "visible",
  "timestamp": 1700000406,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "settings": {
    "struct": {
      "category": {
        "value": "ecommerce"
      },
      "action": {
        "value": "impression"
      },
      "label": "data.name",
      "property": "data.color",
      "value": "data.price"
    }
  }
}
Out
snowplow.trackStructEvent({
  "category": "ecommerce",
  "action": "impression",
  "label": "Everyday Ruck Snack",
  "property": "black",
  "value": 420
})

Transaction

A completed order fires a Snowplow ecommerce transaction action with transaction id, revenue, tax, and shipping.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "f7d1528da8be76ca",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000402,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "transaction",
  "settings": {
    "context": [
      {
        "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/transaction/jsonschema/1-0-0",
        "data": {
          "transaction_id": "data.id",
          "revenue": "data.total",
          "currency": {
            "key": "data.currency",
            "value": "USD"
          },
          "payment_method": {
            "value": "credit_card"
          },
          "tax": "data.taxes",
          "shipping": "data.shipping"
        }
      }
    ]
  }
}
Out
snowplow.trackSelfDescribingEvent({
  "event": {
    "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/snowplow_ecommerce_action/jsonschema/1-0-2",
    "data": {
      "type": "transaction"
    }
  },
  "context": [
    {
      "schema": "iglu:com.snowplowanalytics.snowplow.ecommerce/transaction/jsonschema/1-0-0",
      "data": {
        "transaction_id": "0rd3r1d",
        "revenue": 555,
        "currency": "EUR",
        "payment_method": "credit_card",
        "tax": 73.76,
        "shipping": 5.22
      }
    }
  ]
})

User identity and privacy

Cross-session user stitching

Use userId to link events across sessions when users log in. The ID is set once via Snowplow's setUserId() on the first event where the value resolves:

{
collectorUrl: 'https://collector.example.com',
userId: 'user.id',
}

The userId setting supports walkerOS mapping syntax:

  • 'user.id' from walkerOS user object (recommended)
  • 'globals.user_id' from globals

Anonymous tracking

Enable anonymous tracking for privacy-focused collection or before consent:

{
collectorUrl: 'https://collector.example.com',
anonymousTracking: {
  withServerAnonymisation: true,
  withSessionTracking: true,
},
}

Runtime privacy controls

Control tracking modes at runtime using exported utility functions:

import {
clearUserData,
enableAnonymousTracking,
disableAnonymousTracking,
} from '@walkeros/web-destination-snowplow';

clearUserData();
enableAnonymousTracking({ withServerAnonymisation: true });
disableAnonymousTracking();

Track GDPR/CCPA consent events using Snowplow's Enhanced Consent plugin. The destination automatically reacts to walkerOS consent events and calls the appropriate Snowplow consent methods.

Prerequisites: load the Enhanced Consent plugin via the plugins setting or include it in your Snowplow script bundle.

{
collectorUrl: 'https://collector.example.com',
consent: {
  required: ['analytics', 'marketing'],
  basisForProcessing: 'consent',
  consentUrl: 'https://example.com/privacy',
  consentVersion: '2.0',
  domainsApplied: ['example.com'],
  gdprApplies: true,
},
}
OptionTypeDescription
requiredstring[]walkerOS consent groups to check
basisForProcessingstringGDPR basis: consent, contract, legal_obligation, vital_interests, public_task, legitimate_interests
consentUrlstringPrivacy policy URL
consentVersionstringPolicy version
domainsAppliedstring[]Domains where consent applies
gdprAppliesbooleanWhether GDPR applies

The destination maps walkerOS consent state to Snowplow methods:

walkerOS consent stateSnowplow method
All required scopes grantedtrackConsentAllow
All required scopes deniedtrackConsentDeny
Partial consent (mixed)trackConsentSelected

Media tracking

Track video and audio playback events using Snowplow's media tracking schemas. The destination supports all media events and contexts.

Basic usage

await elb('video play', {
id: 'video-123',
title: 'Product Demo',
currentTime: 0,
duration: 120,
});

await elb('video progress', {
id: 'video-123',
percentProgress: 25,
});

await elb('video pause', {
id: 'video-123',
currentTime: 45,
});

await elb('video end', {
id: 'video-123',
duration: 120,
});

Media mapping configuration

Configure media event mappings with the MEDIA_SCHEMAS constants:

import { MEDIA_SCHEMAS } from '@walkeros/web-destination-snowplow';

{
video: {
  play: {
    settings: {
      snowplow: { actionSchema: MEDIA_SCHEMAS.PLAY },
      context: [{
        schema: MEDIA_SCHEMAS.MEDIA_PLAYER,
        data: {
          currentTime: 'data.currentTime',
          duration: 'data.duration',
          paused: { value: false },
          muted: 'data.muted',
          volume: 'data.volume',
        },
      }],
    },
  },
  progress: {
    settings: {
      snowplow: { actionSchema: MEDIA_SCHEMAS.PERCENT_PROGRESS },
    },
    data: { map: { percentProgress: 'data.percent' } },
  },
},
}

Ad tracking

Track video advertisements with pre-roll, mid-roll, and post-roll events:

import { MEDIA_SCHEMAS } from '@walkeros/web-destination-snowplow';

{
ad: {
  break_start: {
    settings: {
      snowplow: { actionSchema: MEDIA_SCHEMAS.AD_BREAK_START },
      context: [{
        schema: MEDIA_SCHEMAS.AD_BREAK,
        data: {
          breakId: 'data.breakId',
          breakType: 'data.breakType',
        },
      }],
    },
  },
  start: {
    settings: {
      snowplow: { actionSchema: MEDIA_SCHEMAS.AD_START },
      context: [{
        schema: MEDIA_SCHEMAS.AD,
        data: {
          adId: 'data.adId',
          name: 'data.name',
          duration: 'data.duration',
        },
      }],
    },
  },
},
}

Available media schemas

SchemaDescriptionUse case
PLAYPlayback startedVideo/audio play
PAUSEPlayback pausedUser pauses content
ENDPlayback endedVideo/audio completed
SEEK_START / SEEK_ENDUser seekingScrubbing timeline
BUFFER_START / BUFFER_ENDBuffering stateLoading content
QUALITY_CHANGEVideo quality changedAdaptive streaming
FULLSCREEN_CHANGEFullscreen toggledUser interaction
VOLUME_CHANGEVolume changedUser adjustment
PERCENT_PROGRESSProgress milestone25%, 50%, 75% markers
ERRORPlayback errorError tracking
AD_BREAK_START / AD_BREAK_ENDAd breakPre/mid/post-roll
AD_START / AD_COMPLETE / AD_SKIPIndividual adAd impressions

Schema constants

The package exports pre-defined Snowplow schema URIs for use in custom mappings:

import {
SCHEMAS, ACTIONS, WEB_SCHEMAS, CONSENT_SCHEMAS,
MEDIA_SCHEMAS, MEDIA_ACTIONS
} from '@walkeros/web-destination-snowplow';

SCHEMAS.PRODUCT;
SCHEMAS.TRANSACTION;
ACTIONS.ADD_TO_CART;
ACTIONS.TRANSACTION;
WEB_SCHEMAS.LINK_CLICK;
WEB_SCHEMAS.SUBMIT_FORM;
WEB_SCHEMAS.SITE_SEARCH;
MEDIA_SCHEMAS.PLAY;
MEDIA_SCHEMAS.PAUSE;
MEDIA_SCHEMAS.AD_BREAK_START;
CONSENT_SCHEMAS.PREFERENCES;
CONSENT_SCHEMAS.GDPR;

Advanced configuration

Tracker settings

{
collectorUrl: 'https://collector.example.com',
appId: 'my-app',
appVersion: '1.0.0',
discoverRootDomain: true,
cookieSameSite: 'Lax',
contexts: {
  webPage: true,
  session: true,
  performanceTiming: true,
  geolocation: false,
},
}

Activity tracking (page pings)

{
collectorUrl: 'https://collector.example.com',
activityTracking: {
  minimumVisitLength: 10,
  heartbeatDelay: 30,
},
}

Page view tracking

Snowplow's native trackPageView() can be triggered either on init or via a walkerOS event. Both options require explicit configuration. If neither trackPageView nor pageViewEvent is set, no automatic page view tracking occurs.

{
collectorUrl: 'https://collector.example.com',
trackPageView: true,
}
{
collectorUrl: 'https://collector.example.com',
pageViewEvent: 'page view',
}

Plugins

Load Snowplow plugins for automatic tracking. Supports both URL-based plugins (sp.js) and npm BrowserPlugin instances:

{
collectorUrl: 'https://collector.example.com',
plugins: [
  {
    url: 'https://cdn.jsdelivr.net/npm/@snowplow/browser-plugin-link-click-tracking@latest/dist/index.umd.min.js',
    name: ['snowplowLinkClickTracking', 'LinkClickTrackingPlugin'],
    options: { trackContent: true },
  },
],
}

The enable method is derived automatically from the plugin name (LinkClickTrackingPlugin becomes enableLinkClickTracking). Override with enableMethod if needed.

Global contexts

Attach context entities to all events. Supports static objects and dynamic generator functions:

{
collectorUrl: 'https://collector.example.com',
globalContexts: [
  {
    schema: 'iglu:com.example/app_info/jsonschema/1-0-0',
    data: { version: '1.0.0', environment: 'production' },
  },
  () => ({
    schema: 'iglu:com.example/consent/jsonschema/1-0-0',
    data: {
      advertising: document.cookie.includes('ads_consent=1'),
    },
  }),
],
}

Testing with Snowplow Micro

Use Snowplow Micro for local development:

docker run -p 9090:9090 snowplow/snowplow-micro

Configure the destination with collectorUrl: 'http://localhost:9090' and view events at http://localhost:9090/micro/ui.

💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)