EventsEvent Transformations

Event Transformations

Event transformations modify events as they flow through SignalSmith, allowing you to rename events, add or remove properties, filter events, and enrich data without changing your source instrumentation.

Why Transformations?

Transformations solve common data engineering problems at the CDP layer:

  • Standardize naming — Different sources use different naming conventions (order_completed vs Order Completed vs orderCompleted)
  • Remove sensitive data — Strip PII before events reach certain destinations
  • Enrich events — Add computed properties or external data before forwarding
  • Filter noise — Drop events that are not needed downstream to reduce volume and cost
  • Fix instrumentation — Correct property names or types without redeploying source code

Creating a Transformation

Via the UI

  1. Navigate to Events > Transformations
  2. Click Create Transformation
  3. Select the transformation type
  4. Configure the transformation rules
  5. Set the scope (which events or sources this transformation applies to)
  6. Set the priority (order relative to other transformations)
  7. Click Save

Transformation Types

Rename Event

Change the name of an event. The original event name is replaced.

FieldDescription
Source event nameThe original event name to match
Target event nameThe new event name

Example: Rename orderCompleted to Order Completed to standardize across sources.

{
  "type": "rename_event",
  "source_event": "orderCompleted",
  "target_event": "Order Completed"
}

Add Property

Add a new property to matching events with a static value, computed value, or value derived from other properties.

FieldDescription
Property nameThe property to add
Value sourcestatic, copy, template, or lookup
ValueThe value or expression

Examples:

// Static value
{
  "type": "add_property",
  "property": "source_platform",
  "value_source": "static",
  "value": "web"
}
 
// Copy from another property
{
  "type": "add_property",
  "property": "user_email",
  "value_source": "copy",
  "value": "traits.email"
}
 
// Template with interpolation
{
  "type": "add_property",
  "property": "full_name",
  "value_source": "template",
  "value": "{{first_name}} {{last_name}}"
}

Remove Property

Strip a property from matching events. Useful for removing PII or unnecessary data before forwarding.

FieldDescription
Property nameThe property to remove
{
  "type": "remove_property",
  "property": "ip_address"
}

You can remove multiple properties by creating multiple remove transformations or by specifying an array of property names:

{
  "type": "remove_property",
  "properties": ["ip_address", "user_agent", "device_id"]
}

Rename Property

Change a property name without modifying its value.

FieldDescription
Source propertyThe original property name
Target propertyThe new property name
{
  "type": "rename_property",
  "source_property": "user_id",
  "target_property": "userId"
}

Filter Event

Drop events that match specified conditions. Filtered events are not forwarded, not written to the warehouse, and not counted toward volume limits.

FieldDescription
Actiondrop (remove matching events) or keep (only keep matching events)
ConditionsOne or more conditions to evaluate
// Drop all events from internal users
{
  "type": "filter_event",
  "action": "drop",
  "conditions": [
    { "property": "context.traits.email", "operator": "contains", "value": "@internal.example.com" }
  ]
}
 
// Only keep events with a userId (drop anonymous events)
{
  "type": "filter_event",
  "action": "keep",
  "conditions": [
    { "field": "userId", "operator": "is_set" }
  ]
}

Enrich with External Data

Add properties by looking up values from an external source. Currently supported enrichment sources:

SourceDescription
Lookup tableA key-value table uploaded to SignalSmith (e.g., country code to region mapping)
HTTP lookupCall an external API to fetch enrichment data (with caching)
// Lookup table enrichment
{
  "type": "enrich",
  "source": "lookup_table",
  "table": "country_regions",
  "lookup_key": "properties.country_code",
  "output_property": "properties.region"
}
 
// HTTP enrichment
{
  "type": "enrich",
  "source": "http",
  "url": "https://api.internal.example.com/users/{{userId}}/segment",
  "method": "GET",
  "output_property": "properties.user_segment",
  "cache_ttl_seconds": 3600,
  "timeout_ms": 500
}

HTTP enrichments have a timeout (default 500ms) and a cache to avoid excessive API calls. If the lookup fails, the event passes through without the enrichment property.

Transformation Scope

Each transformation can be scoped to apply to specific events or sources:

ScopeDescription
All eventsApplies to every event regardless of name or source
Specific eventsOnly applies to events with matching names (e.g., Order Completed, Product Viewed)
Specific sourcesOnly applies to events from specified write keys (e.g., only web events)
Event typeOnly applies to specific event types (track, identify, page, screen, group)

Scopes can be combined. For example, “Rename user_id to userId for track events from the mobile write key.”

Transformation Pipeline Order

When multiple transformations apply to the same event, they execute in priority order (lowest number first):

Event received

Priority 1: Rename event "orderCompleted" → "Order Completed"

Priority 2: Add property "source_platform" = "web"

Priority 3: Remove property "ip_address"

Priority 4: Enrich with region lookup

Priority 5: Filter (drop internal users)

Transformed event → forwarding / warehouse

Each transformation receives the output of the previous one. This means:

  • A rename transformation at priority 1 changes the event name, so a scope filter at priority 2 should use the new name
  • A remove transformation removes a property, so subsequent transformations cannot reference it
  • A filter transformation at the end drops the event after all other transformations have been applied

Reordering

To change the execution order, update the priority numbers in the transformations list. You can drag-and-drop transformations in the UI to reorder them.

Testing Transformations

Before activating a transformation, test it with sample events:

  1. Open the transformation configuration
  2. Click Test
  3. Paste a sample event JSON or select from recent events
  4. View the transformation output — the modified event is shown alongside the original for comparison

Testing does not affect live event processing.

API Reference

# List transformations
GET /api/v1/events/transformations
 
# Create a transformation
POST /api/v1/events/transformations
 
# Update a transformation
PUT /api/v1/events/transformations/{id}
 
# Delete a transformation
DELETE /api/v1/events/transformations/{id}
 
# Test a transformation
POST /api/v1/events/transformations/test

Best Practices

  • Order matters — Place rename and add transformations before filter transformations so filters can reference the final property names
  • Test before deploying — Always test with sample events to verify the transformation produces the expected output
  • Document your transformations — Use the description field to explain why each transformation exists. Future team members will thank you.
  • Monitor transformation impact — Check the events dashboard to verify event volume and properties after activating a new transformation
  • Prefer contracts over filters for validation — Use event contracts for schema enforcement and transformations for data modification