# Custom Events (/docs/sdk/custom-events)



Use a custom event name when your action doesn't fit a
[standard event](/docs/sdk/standard-events).

## Naming rules [#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 [#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](/docs/sdk/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? [#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:

```ts
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 [#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 [#best-practice]

Define a controlled vocabulary in your codebase:

```ts
// 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.
