Event Specs
Datafly Signal uses a consistent set of snake_case event IDs across all verticals. These IDs are:
- The value sent in the
eventfield by Datafly.js (e.g.datafly.track('add_to_cart', {...})) - The key used in your pipeline’s Per-Event Parameters configuration
- The stable identifier used for vendor event name mapping
Using the standard event IDs from these specs means your pipelines stay compatible with pre-built blueprints and vendor mapping tables — you won’t need to manually configure the event name for each destination.
How event IDs work
Every event flowing through Signal has an event field:
{
"type": "track",
"event": "add_to_cart",
"properties": {
"currency": "GBP",
"value": 79.99,
"items": [
{ "item_id": "SKU-001", "item_name": "Running Shoes", "price": 79.99, "quantity": 1 }
]
}
}The pipeline engine looks up the event value against your Per-Event Parameters configuration. If a matching
section exists, those field mappings are applied on top of the global parameters before delivery to the vendor.
Built-in events
These events are sent automatically by Datafly.js without any track() call:
| Event ID | Sent by | Description |
|---|---|---|
page | datafly.page() | Page view. Fired automatically on each page load. Pass page_type to classify it (see below). |
identify | datafly.identify(userId, traits) | Links anonymous visitor to a known user. |
group | datafly.group(groupId, traits) | Associates user with a company or account. |
Classifying page views with page_type
page is vertical-neutral and fires on every page load, so on its own it says nothing about what kind of page was viewed. Several destinations model page views by type rather than as one undifferentiated event, and can only report properly when they know which.
Pass an optional page_type to classify it:
datafly.page({ page_type: 'content' })| Value | Use for |
|---|---|
homepage | The site homepage |
category | A listing, category, or index page |
product | A product detail page |
search | A search results page |
content | An article, post, guide, or other content item |
thematic | A themed or SEO landing page |
other | Anything that doesn’t fit the above |
Destinations that don’t model page types ignore it. Destinations that do fall back to their generic page type when it’s absent or unrecognised, so adding it can only improve fidelity, never break a working integration.
Don’t send both a typed page and a separate page-view event for the same page load. On destinations whose page-view events are their page-type taxonomy, that counts the view twice with two conflicting types. Retail sites firing view_item and view_item_list should generally leave page unmapped for those destinations; non-retail sites should use typed page as their single page-view event.
Common events
These optional events apply across any vertical. They’re documented here so they map consistently across destinations.
| Event ID | Description | GA4 | Meta CAPI |
|---|---|---|---|
generate_lead | A lead / enquiry was submitted (form, demo, quote). Hash PII via identify(). | generate_lead | Lead |
donation_made | A donation was completed (treated as a conversion). | purchase | Purchase |
cta_clicked | A call-to-action button was clicked. | select_content | (custom) |
element_clicked | A tracked UI element was clicked. | select_content | (custom) |
error_occurred | A client or checkout error occurred (diagnostic). | (custom) | (custom) |
user_updated | A user updated their profile or account details. | (custom) | (custom) |
consent | A communications consent was granted or withdrawn (see below). | (custom) | (custom) |
consent
Fired when a user grants or withdraws consent for a communications channel or purpose: a newsletter opt-in, an SMS marketing checkbox, a preference-centre change, an unsubscribe.
datafly.track('consent', {
consent_category: 'weekly_newsletter', // your own category identifier
consent_action: 'granted', // 'granted' | 'denied'
consent_message: 'Send me weekly offers', // what the user actually saw
consent_valid_until: 'unlimited' // optional; 'unlimited' or a timestamp
})| Property | Type | Required | Description |
|---|---|---|---|
consent_category | string | Required | Your identifier for the thing being consented to. Must match the category defined in the destination. |
consent_action | string | Required | granted or denied. Destination blueprints value-map this to vendor wording. |
consent_message | string | Optional | Verbatim text the user reacted to. This is what makes the record defensible to a regulator. |
consent_valid_until | string | Optional | unlimited, or when the consent expires. |
The event timestamp is the moment consent was given, and destinations treat it as the consent’s valid_from. Fire this event on change only, never on every page load: repeating a grant floods the profile and destroys the audit trail’s meaning.
This is not cookie consent, and the two must never be wired together. Cookie and tracking consent lives in context.consent.*, is collected by your CMP, and is what Signal uses to gate whether a destination receives data at all. This event is about permission to communicate with someone.
They are different permissions with different legal bases. Mapping a cookie-banner category onto a communications category means a visitor declining analytics cookies gets unsubscribed from your email programme. Some destinations treat a withdrawal as immediate and irreversible, so that mistake is not recoverable by resending.
Because this event carries a permission decision rather than behavioural data, destinations that accept it may receive it even where the cookie-consent gate would otherwise close, but only where an operator has explicitly configured that destination to accept consent from Signal. It is off by default everywhere.
Vertical specs
Choose the spec that matches your business model. You can mix events from multiple verticals — a subscription news site might use both Publishing and SaaS events.
Property conventions
All event properties use snake_case:
// Correct
datafly.track('purchase', {
transaction_id: 'ORD-1234',
value: 129.99,
currency: 'GBP',
items: [{ item_id: 'SKU-001', item_name: 'Trainers', price: 79.99, quantity: 1 }],
});
// Avoid
datafly.track('purchase', {
transactionId: 'ORD-1234', // camelCase — avoid
Value: 129.99, // PascalCase — avoid
});Standard monetary properties:
| Property | Type | Description |
|---|---|---|
revenue | number | Total revenue including tax and shipping |
value | number | Conversion value (use when revenue doesn’t apply) |
currency | string | ISO 4217 currency code (GBP, USD, EUR) |
price | number | Unit price |
Never include raw PII (email addresses, phone numbers, full names) in track() properties.
Use datafly.identify() to attach user traits — Signal hashes PII server-side before
delivering to vendors.