Custom Events
What happens when you call track() with an event name outside the standard list.
Use a custom event name when your action doesn't fit a standard event.
Naming rules
The SDK itself does not enforce a name format — any non-empty string is accepted. Recommended conventions:
snake_case.- Verb-noun:
completed_onboarding,hit_streak_day_7. - Lowercase, no spaces or slashes.
- Keep it short and stable — event names fragment dashboards when they drift.
What happens to custom events
| System | Behavior |
|---|---|
sdk_events table | Stored. |
| Layers Events page | Shown. |
| Funnel / cohort analysis | Available. |
| Meta CAPI | Dropped at the relay unless a per-app event_map override maps it to a standard Meta event. |
| TikTok Events API | Dropped at the relay unless mapped via a per-app event_map. |
| Apple Search Ads | Not involved — ASA uses install + post-install conversion signals, not SDK events. |
The relay's default behavior is to forward only the events in the
standard events mapping table. If you need
a custom event to reach a platform, add a mapping in the ads layer's
CAPI config (event_map).
Should I use custom for purchases?
No. Use purchase_success (or paywall_purchased) so Meta and TikTok
see it as a standard Purchase event without any extra config. Add
whatever extra context you want as custom properties:
layers.track('purchase_success', {
revenue: 9.99,
currency: 'USD',
product_id: 'premium_yearly',
transaction_id: 'txn_...',
// custom properties:
promo_code: 'SAVE20',
acquisition_source: 'youtube_referral',
});Volume considerations
There's no Layers-side limit on custom event names. Meta limits per Pixel to 10 standard + 40 custom event types across your ad account — if you expose thousands of fine-grained custom events and try to map them all, Meta will start dropping.
Best practice
Define a controlled vocabulary in your codebase:
// events.ts
export const Events = {
ONBOARDING_COMPLETED: 'onboarding_completed',
STREAK_HIT: 'streak_hit',
REFERRAL_SENT: 'referral_sent',
} as const;
layers.track(Events.STREAK_HIT, { day: 7 });Avoid free-form event names emitted from different call sites with slight variations — they fragment dashboards and make downstream analysis painful.