Product analytics Required
Validate every event before you store it
Check each incoming event against its schema at the collector. Store valid events, and set invalid ones aside with the reason.
How to do it
Compile the tracking plan into JSON Schema 2020-12 validators, such as Ajv's Ajv2020 class or Python's jsonschema. Reject unknown events, unknown properties and wrong types. Write rejects to a separate table with the error and the app version, as with a dead letter queue. Alert when rejects pass 1 percent of events in an hour, because a release has broken tracking.
Example
import Ajv2020 from 'ajv/dist/2020.js';
const ajv = new Ajv2020({ allErrors: true });
const validators = Object.fromEntries(Object.entries(EVENT_SCHEMAS).map(([name, schema]) => [name, ajv.compile(schema)]));
export async function collect(event) {
const validate = validators[event.name];
if (validate?.(event.properties)) return db.events.insert(event);
return db.eventRejects.insert({ event, error: validate ? ajv.errorsText(validate.errors) : 'unknown event' });
}
from jsonschema import Draft202012Validator
VALIDATORS = {name: Draft202012Validator(schema) for name, schema in EVENT_SCHEMAS.items()}
def collect(event: dict):
validator = VALIDATORS.get(event["name"])
errors = [e.message for e in validator.iter_errors(event["properties"])] if validator else ["unknown event"]
if errors:
return db.event_rejects.insert(event=event, error="; ".join(errors))
return db.events.insert(event)
How to check
Send one valid and one invalid event to the staging collector. The valid one is in the events table, and the invalid one is in the rejects table with its error.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers data playbook: https://agentwranglers.se/playbook/data/product-analytics/event-validation.