Skip to main content
GUIDE · RUDDERSTACK8 min read

RudderStack + TrackLayer: open-source CDP + server-side CAPI

A practical setup for teams that want RudderStack to keep collecting raw first-party events while TrackLayer turns the conversion-grade subset into canonical server-side delivery for ad platforms, email tools, and other downstream destinations.

Context

Why RudderStack + TrackLayer

RudderStack is valuable because it keeps the raw event stream open. Teams can capture browser, app, and backend activity, standardize schemas enough to stay sane, and push the original payloads into warehouses, lakehouses, and internal pipelines without immediately committing every event to a marketing-specific interpretation. That makes it a strong fit for engineering teams that want ownership over collection and storage instead of hiding the event pipe behind a black-box destination layer.

TrackLayer solves a different problem. It takes the smaller set of events that actually matter for activation and turns them into a stable canonical contract for server-side CAPI delivery. In practice, RudderStack keeps collecting raw facts, while TrackLayer decides which facts become `purchase`, `lead`, `begin_checkout`, or other destination-ready actions with normalized properties, identity enrichment, consent enforcement, deduplication, and observability attached.

Architecture

2 paths

Path 1

Self-hosted RS → TrackLayer destination

Run your own RudderStack control plane and data plane, then add TrackLayer as an HTTP destination in the data plane config. This path is useful when infrastructure teams want control over VPC routing, custom transforms, regional residency, or direct warehouse fan-out from the same cluster.

Path 2

RS Cloud → TrackLayer destination

Use RudderStack Cloud for collection, transformations, retries, and destination management, then configure TrackLayer as a managed webhook-style destination. This is the fastest route when you want less operational overhead but still need server-side canonicalization and downstream CAPI delivery.

Build

Setup

Step 1

Provision a dedicated TrackLayer endpoint

Create a TrackLayer inbound destination for RudderStack and keep it isolated from browser-native feeds. Give staging and production their own URLs and secrets so delivery logs stay readable and environment crossover never happens. Start with a narrow allowlist such as product, checkout, purchase, lead, and signup events before adding more noisy lifecycle calls.

endpoint:
  url: https://inbound.tracklayer.io/rudderstack/events
  secret_ref: TRACKLAYER_DESTINATION_SECRET
  environment: production
  source: rudderstack
Step 2

Add the Data Plane destination template

For self-hosted RudderStack, define TrackLayer as an HTTP-capable destination in the data plane so events can be posted with stable headers. The important part is that RudderStack preserves message identifiers and timestamps while sending a TrackLayer account header, environment header, and shared signature secret. That gives TrackLayer enough context to accept, validate, and deduplicate incoming requests.

destinations:
  - name: tracklayer-http
    enabled: true
    type: http
    config:
      endpoint: https://inbound.tracklayer.io/rudderstack/events
      method: POST
      headers:
        Content-Type: application/json
        X-TrackLayer-Account: acct_live_123
        X-TrackLayer-Environment: production
        X-TrackLayer-Secret: ${TRACKLAYER_DESTINATION_SECRET}
      retry:
        maxAttempts: 5
        backoffMs: 2000
Step 3

Shape the outbound payload

RudderStack already emits a predictable event envelope, but TrackLayer should receive a thinner, destination-grade body. Keep the original RudderStack message ID, event type, identifiers, traits, and commerce properties, then flatten only the fields TrackLayer needs to create a canonical event. This makes downstream debugging much easier because raw and canonical payloads remain obviously related.

transform:
  template: |
    {
      "message_id": "{{ .messageId }}",
      "type": "{{ .type }}",
      "event": "{{ .event }}",
      "sent_at": "{{ .sentAt }}",
      "anonymous_id": "{{ .anonymousId }}",
      "user_id": "{{ .userId }}",
      "traits": {{ toJson .traits }},
      "properties": {{ toJson .properties }}
    }
Step 4

Configure RS Cloud or source-side filters

Whether you are using RudderStack Cloud or self-hosted transforms, apply filters before TrackLayer to prevent low-value events from becoming noisy server-side traffic. Page views, generic clicks, and internal instrumentation events usually belong in raw analytics and the warehouse, not in conversion APIs. The cleaner your allowlist is, the easier it is to keep event naming, consent logic, and downstream spend reporting consistent.

filters:
  include:
    - Product Viewed
    - Product Added
    - Checkout Started
    - Order Completed
    - Lead Submitted
    - Signed Up
Step 5

Validate end-to-end delivery

Send one identify call and one purchase-style event for a controlled test user, then inspect both systems. RudderStack should show a successful delivery attempt with the expected headers and body. TrackLayer should show an accepted inbound request, a canonical event name, a resolved identity record, and a reusable event_id for downstream APIs. Only widen the event allowlist after that trace is reliable.

validate:
  rudderstack: delivered
  tracklayer:
    accepted: true
    canonical_event: purchase
    identity_state: merged
    downstream_ready: true
Schema

Event mapping

RudderStack event names are often collection-oriented, while TrackLayer canonical names are activation-oriented. Keeping a small translation table avoids coupling downstream systems to frontend naming drift. Product teams can keep readable event names, warehouse teams still get raw detail, and TrackLayer can present one canonical contract to Meta, Google, Klaviyo, TikTok, internal webhooks, and anything else on the other side.

RS event typeTrackLayer canonical
pagepage_view
track: Product Viewedview_content
track: Product Addedadd_to_cart
track: Checkout Startedbegin_checkout
track: Order Completedpurchase
track: Lead Submittedlead
track: Signed Upsign_up
identifyprofile_update
Warehouse

Warehouse destinations

A strong RudderStack pattern is to send the raw stream into BigQuery or Snowflake at the same time that selected events are forwarded to TrackLayer. The warehouse keeps your uncompressed source-of-truth history for modeling, attribution, reverse ETL, product analytics, and replay. TrackLayer, in parallel, receives only the events that should become destination-grade conversions.

This split removes a common tradeoff. You do not have to choose between pristine raw data and operational marketing delivery. RudderStack can continue writing `track`, `page`, `screen`, `identify`, and backend events to analytical storage, while TrackLayer converts a narrower lane into canonical actions with value, currency, items, order IDs, hashed identifiers, consent, and destination-specific retry logic. Warehouse reliability stays intact, and CAPI delivery stops depending on ad-hoc SQL jobs or direct app code.

Identity

Identity resolution interop

RudderStack IdentifyResolve can unify identifiers at collection time by connecting anonymous IDs, known user IDs, email addresses, phone numbers, and source-specific traits into a more coherent profile record. That is useful because TrackLayer should not have to infer everything from a single purchase event. The richer the incoming identity envelope is, the less work happens at the moment of conversion.

TrackLayer then applies its own union-find identity model on top of that stream. In practice, RudderStack contributes edges between identifiers as events are collected, and TrackLayer merges those edges with downstream facts such as order email, CRM external IDs, loyalty IDs, or server-enriched contact fields. The two systems do not need to compete. RudderStack helps create earlier identity joins, while TrackLayer keeps the activation graph stable and reusable across destinations. The result is fewer unmatched conversions, fewer duplicate profiles, and less brittle logic in every single destination adapter.

RudderStack IdentifyResolve → emits linked identifiers
TrackLayer union-find → extends and stabilizes the activation graph
FAQ

Common questions

Does TrackLayer replace RudderStack?

No. RudderStack remains the collection and routing layer. TrackLayer sits downstream for the subset of events that need canonical commerce semantics, stricter identity handling, consent-aware delivery, and server-side destination APIs.

Should I send every RudderStack event to TrackLayer?

Usually not. Keep broad behavioral telemetry in RudderStack and the warehouse. Send only the events that benefit from canonical naming and activation, such as lead, signup, cart, checkout, purchase, refund, or other revenue-linked moments.

Can I use TrackLayer if RudderStack already writes to BigQuery or Snowflake?

Yes. That is one of the strongest patterns. RudderStack can keep writing raw and semi-modeled events to the warehouse while TrackLayer receives a parallel stream for destination delivery, observability, and CAPI-specific normalization.

Where should consent logic live?

Capture the source consent state in RudderStack context or traits, but evaluate destination-specific enforcement in TrackLayer. That lets one collected event fan out differently to Meta, Google, email, or internal webhooks without duplicating consent code everywhere.

What is the right dedup key?

Use the RudderStack message ID as the transport dedup foundation, then combine it with business identifiers where appropriate, such as order_id for purchase or lead_id for lead. TrackLayer should preserve that event_id across all downstream retries.

Next reads

Related implementation guides

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.