Unity SDK

Tracking events

The TrackEvent API surface, property rules, validation, global properties, and revenue helpers.

The basics

// Bare event
ReflectSDK.TrackEvent("level_started");

// Event with properties
ReflectSDK.TrackEvent("level_started", new Dictionary<string, object> {
    { "level",      3 },
    { "difficulty", "hard" },
    { "from_menu",  true },
});

Events are queued, batched, and sent every 30 seconds (or 50 events, whichever comes first). They survive app kill — the queue is persisted to disk on pause.

Property types

Anything JSON-serializable works:

  • string, int, long, float, double, bool
  • DateTime / DateTimeOffset — converted to ISO-8601 in UTC
  • Nested IDictionary / arrays (1 level deep)
  • null — preserved

Anything else gets .ToString()’d.

Validation rules

The SDK validates client-side so you never spend Cloudflare bandwidth on rejected events:

LimitValueDrop reason
Event name1–64 chars, [a-z][a-z0-9_-]*event_name_invalid_chars
Properties per event≤ 25too_many_props
Property key length≤ 40 charsbad_prop_key
Property string value length≤ 1024 chars (truncated)silent truncation

Underscore-prefixed names (e.g. _user_alias, _crash) are reserved for SDK-internal events.

Global properties

Set values once, get them merged into every event:

ReflectSDK.SetGlobalProperty("user_tier",   "premium");
ReflectSDK.SetGlobalProperty("ab_variant",  "B");
ReflectSDK.SetGlobalProperty("app_locale",  Application.systemLanguage.ToString());

// Per-event props win on key collision
ReflectSDK.TrackEvent("level_complete", new Dictionary<string, object> {
    { "level", 5 },
    { "user_tier", "trial" },   // overrides the global for this one event
});

// Remove
ReflectSDK.UnsetGlobalProperty("ab_variant");

// Wipe all
ReflectSDK.ClearGlobalProperties();

Revenue events

Three flavors with progressively more affordances:

// 1) Manual — full control
ReflectSDK.TrackEvent("purchase", new Dictionary<string, object> {
    { "product_id",     "sku_pro_pack" },
    { "price_local",    9.99 },
    { "currency_code",  "USD" },
    { "transaction_id", "txn_abc123" },
});

// 2) Helper with revenue fields
ReflectSDK.TrackPurchase(
    productId:     "sku_pro_pack",
    price:         9.99,
    currencyCode:  "USD",
    transactionId: "txn_abc123",
    receiptData:   storeKitReceiptBase64   // optional — server validates
);

// 3) Subscription helpers
ReflectSDK.TrackSubscription(
    productId:     "sub_monthly",
    price:         4.99,
    currencyCode:  "USD",
    transactionId: "sub_txn_xyz",
    isTrial:       false
);
ReflectStandardEvents.SubscriptionDidRenew("sub_monthly", 4.99, "USD", "txn_renew");
ReflectStandardEvents.SubscriptionDidCancel("sub_monthly", reason: "user_cancelled");
About receipt_data
Pass the raw StoreKit receipt (iOS, base64) or the Play Billing purchase token (Android). Reflect’s server will call Apple/Google to verify it and flip attributions.is_revenue_validated on success. Spoofed receipts get fraud_flag’d. See REST API.

Force flush

The SDK flushes automatically every 30s, on app_pause, and when BatchSize is reached. If you need to flush manually (e.g. just before a critical screen exit):

ReflectSDK.Flush();

Standard event names

Reflect ships a vocabulary of pre-defined event names + typed helpers matching AppsFlyer / Firebase conventions. See Standard events.