Skip to content

TrackingControl

Ahmed Abbas edited this page Jun 8, 2026 · 1 revision

Tracking Control

Two independent switches control whether the SDK sends outbound tracking events: a global config switch and a per-call override. Use them to honor consent without losing your experiment logic — bucketing, rule evaluation, and sticky persistence keep working regardless of the tracking state. Only the outbound network enqueue is silenced.

The global switch — tracking:

Set tracking: false at ConvertSdk.create to disable all outbound event tracking for the client:

CONVERT_SDK = ConvertSdk.create(
  sdk_key:  ENV.fetch("CONVERT_SDK_KEY"),
  tracking: false   # default is true
)

When tracking is false:

  • Decisioning still runs. run_experience / run_features etc. still bucket the visitor and return real results.
  • Sticky StoreData still persists. Variation assignments and visitor properties are still written to the store.
  • The outbound event enqueue is suppressed. No bucketing event is enqueued for delivery, and a debug line records each suppression (tracking disabled, event suppressed).

Conversions under the global switch

track_conversion checks the global switch before the dedup-and-mark step. So when tracking is false a conversion is neither enqueued nor marked as deduplicated — meaning a subsequent same-goal call stays unblocked once tracking is re-enabled. The return value is unchanged (self); no sentinel:

context.track_conversion("purchase")
# tracking: false -> nothing enqueued, goal NOT marked, debug line emitted, returns self

The per-call override — enable_tracking

Suppress the event for a single decision call by putting enable_tracking: false in the per-call attributes hash (symbol or string key both work — the public boundary accepts both):

variation = context.run_experience("homepage-test", { enable_tracking: false })
context.run_experiences({ enable_tracking: false })

When enable_tracking: false, bucketing, sticky persistence, audience rules, and the internal bucketing lifecycle event still fire — only the outbound enqueue is skipped (a debug line records the suppression: tracking suppressed for call). Absent or any non-false value leaves tracking on; only an explicit false suppresses.

The bucketing lifecycle event always fires — it is decisioning observability, not tracking, so a host listener can react to the decision even under consent denial. Only the outbound enqueue is gated by the tracking switches.

How the two combine — global-off always wins

The verdict for whether an event is enqueued is the composition of both switches. The global switch is dominant: a global tracking: false suppresses delivery regardless of a per-call enable_tracking: true.

Global tracking Per-call enable_tracking Event enqueued?
true true (default) Yes
true false No
false true No (global-off wins)
false false No

Consent scenarios

Scenario What to do
Consent denied for the whole client ConvertSdk.create(..., tracking: false). Decisions and stickiness still work; nothing is delivered.
Consent denied for a specific call only Keep the global tracking: true and pass enable_tracking: false on the calls you want silent.
Diagnosing "events vanish" Confirm tracking is not disabled — a tracking disabled, event suppressed / tracking suppressed for call debug line is the signal. See the missing-events decision tree.

Related pages

Clone this wiki locally