Blog

How to Create Custom Self-Describing Events and Contexts in Snowplow

By
Snowplow Team
&
April 17, 2024
Share this post

Snowplow supports a rich set of first-class events out of the box — from page views to e-commerce transactions. But what if you need to track an interaction that’s specific to your product or business model?

That’s where self-describing events and custom contexts come in. In this guide, we answer common questions and walk you through how to define, track, and validate your own custom events using Snowplow’s Iglu schema system.

What are self-describing events and why use them?

Self-describing events let you track custom behaviors that Snowplow doesn’t model by default. Unlike structured events (which use predefined fields like se_category and se_action), self-describing events reference a JSON Schema that validates the shape and contents of the payload.

You’ll want to use self-describing events when:

  • Your use case is domain-specific (e.g., tracking ad impressions, game interactions, IoT sensor readings).

  • You need strong schema enforcement and versioning.

  • You want to extend Snowplow’s canonical event model with additional metadata.

Tip: Use structured events for simple analytics use cases. Use self-describing events for anything custom or complex.

How do I create and track a self-describing event?

Here’s a step-by-step overview:

1. Identify the event to track

Let’s say you want to track hover interactions on images. You have the following HTML:

<p><img id="First" onmouseover="smallImg(this)" onmouseout="normalImg(this)" src="pic1.jpg"></p>
<p><img id="Second" onmouseover="smallImg(this)" onmouseout="normalImg(this)" src="pic2.jpg"></p>
Your JavaScript functions might look like this:
function smallImg(x) {
  x.style.height = "50px";
}

Now you want to track that event in Snowplow.

2. Use trackSelfDescribingEvent in your tracker

Update your JavaScript function to emit a self-describing event:

function smallImg(x) {
  x.style.height = "50px";
  var data = {
    "imgId": x.id,
    "imgSrc": x.src,
    "imgEvent": "smallImg"
  };
  window.snowplow('trackSelfDescribingEvent', {
    schema: 'iglu:com.example_company/onmouse_img/jsonschema/1-0-0',
    data: data
  });
}

3. Define a JSON Schema

Create a JSON Schema for your event:

{
  "$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
  "description": "onmouse_img example",
  "self": {
    "vendor": "com.example-company",
    "name": "onmouse_img",
    "format": "jsonschema",
    "version": "1-0-0"
  },
  "type": "object",
  "properties": {
    "imgId": { "type": "string" },
    "imgSrc": { "type": "string" },
    "imgEvent": { "enum": ["smallImg", "normalImg"] }
  },
  "required": ["imgId", "imgSrc", "imgEvent"],
  "additionalProperties": false
}

4. Validate your schema with igluctl

$ ./igluctl lint ~/schemas/com.example-company/onmouse_img/jsonschema/1-0-0

You should see a success message if your schema is valid.

5. Upload schema to your Iglu registry

You’ll need an Iglu-compatible schema registry, such as:

  • Iglu Central (Snowplow’s open registry)

  • Your own static S3-hosted Iglu

  • Iglu Server (Docker-compatible REST API)

Example resolver.json config with your static Iglu:

{
  "schema": "iglu:com.snowplowanalytics.iglu/resolver-config/jsonschema/1-0-1",
  "data": {
    "cacheSize": 500,
    "repositories": [
      {
        "name": "Iglu Central",
        "priority": 0,
        "vendorPrefixes": ["com.snowplowanalytics"],
        "connection": { "http": { "uri": "http://iglucentral.com" } }
      },
      {
        "name": "Your own Iglu",
        "priority": 1,
        "vendorPrefixes": ["com.example-company"],
        "connection": {
          "http": {
            "uri": "http://your-iglu-registry.s3-website-region.amazonaws.com"
          }
        }
      }
    ]
  }
}

6. Generate JSONPaths and SQL definitions

Use igluctl to generate both:

$ ./igluctl static generate ~/schemas/com.example-company/onmouse_img/jsonschema/1-0-0 --with-json-paths --output ~/
Example JSONPaths file:
{
  "jsonpaths": [
    "$.data.imgEvent",
    "$.data.imgId",
    "$.data.imgSrc"
  ]
}

7. Create the Redshift table

Example SQL (auto-generated by igluctl):

CREATE TABLE IF NOT EXISTS atomic.com_example_company_onmouse_img_1 (
  "img_event" VARCHAR(9) ENCODE LZO NOT NULL,
  "img_id" VARCHAR(4096) ENCODE LZO NOT NULL,
  "img_src" VARCHAR(4096) ENCODE LZO NOT NULL,
  ...
);
ALTER TABLE atomic.com_example_company_onmouse_img_1 OWNER TO storageloader;

Tip: Set correct permissions so the storageloader user can load data.

Can I use se_category or se_action in a self-describing event?

No. se_category and related fields are part of the structured event model. If you’re emitting a self-describing event, all values must conform to the JSON Schema you define.

If you need to track those values, define them as top-level fields in your schema (e.g., "category": "interaction").

How should I test new self-describing events?

Always test your schemas using Snowplow Mini or a non-production pipeline first. Common issues include:

  • Schema validation failures (missing required fields)
  • Mistyped schema URIs
  • Incomplete JSONPaths for Redshift or BigQuery

What tools help with schema development?

  • igluctl — validate schemas, generate JSONPaths and SQL
  • Snowplow Mini — real-time testing environment
  • Snowplow Micro — lightweight validation API for CI/CD
  • SnowcatCloud Registry — managed Iglu registry with version history

Any differences if I'm using BigQuery or Snowflake?

Yes — if you're using BigQuery or Snowflake:

  • JSONPaths are not required.
  • You don’t need to create SQL tables manually.
  • Schemas are inferred and loaded dynamically based on the event payloads.

Final thoughts

Snowplow’s support for self-describing events makes it an incredibly flexible event tracking platform. Whether you’re measuring in-game actions, financial events, or ad interactions, custom schemas give you the structure and governance you need — without sacrificing flexibility.

🧠 Next step: Define and deploy a real schema for your business use case. Then integrate and test using Snowplow Mini or Micro.

Have questions or run into issues? Reach out to us directly.

Subscribe to our newsletter

Get the latest content to your inbox monthly.

Get Started

Whether you’re modernizing your customer data infrastructure or building AI-powered applications, Snowplow helps eliminate engineering complexity so you can focus on delivering smarter customer experiences.