# Migrate from AppsFlyer (/docs/sdk/migration-appsflyer)



If you already have AppsFlyer installed and want to add or migrate to
Layers, the safest path is **dual-send overlap**: run both SDKs for
\~14 days, reconcile, then decide whether to drop AppsFlyer.

## Why dual-send [#why-dual-send]

* Validate Layers' attribution numbers against AppsFlyer's baseline.
* Identify event-name mapping gaps before cutting over.
* Provide a rollback path if Layers' numbers don't look right.

## Event-name mapping [#event-name-mapping]

Use Layers' [standard events](/docs/sdk/standard-events) where possible
so the CAPI relay can forward them to Meta / TikTok without a custom
`event_map` override. A reasonable starting translation:

| AppsFlyer event            | Layers event                            |
| -------------------------- | --------------------------------------- |
| `af_purchase`              | `purchase_success`                      |
| `af_subscribe`             | `subscription_start`                    |
| `af_complete_registration` | `sign_up`                               |
| `af_add_to_cart`           | `add_to_cart`                           |
| `af_initiate_checkout`     | `purchase_attempt`                      |
| `af_search`                | `search`                                |
| `af_content_view`          | `content_open`                          |
| `af_tutorial_completion`   | custom (no default Meta/TikTok mapping) |
| `af_level_achieved`        | custom                                  |
| `af_login`                 | custom                                  |

If you have custom AppsFlyer events (`af_*` you've defined), decide
case-by-case: map to a standard Layers event (forwarded automatically)
or keep as a custom Layers event (stored only, not forwarded unless you
add an `event_map` override).

## Dual-send sketch [#dual-send-sketch]

```ts
// AppsFlyer (existing)
appsflyer.logEvent('af_purchase', { af_revenue: 9.99, af_currency: 'USD' });

// Layers (added) — same event
layers.track('purchase_success', {
  revenue: 9.99,
  currency: 'USD',
  product_id: 'premium_yearly',
  transaction_id: 'txn_...',
});
```

Run both for \~14 days. Compare:

* AppsFlyer installs vs Layers install\_id counts.
* AppsFlyer purchase count vs Layers `purchase_success` count in the
  Events page.
* Meta / TikTok dashboards vs Layers' reported CAPI deliveries on the
  ad-layer overview tab.

## Expected divergence [#expected-divergence]

* For Meta + TikTok attribution, Layers should match or beat AppsFlyer
  (server-side CAPI vs client-side pixel).
* For Apple Search Ads, both should be near-identical (both use the
  attribution token).
* For non-Meta / non-TikTok / non-Apple ad networks, AppsFlyer has
  coverage that Layers does not — keep AppsFlyer for those.

## Options after reconciliation [#options-after-reconciliation]

1. **Keep both.** AppsFlyer for non-Meta/TikTok/Apple networks; Layers
   for Meta + TikTok + Apple Search + organic + content.
2. **Remove AppsFlyer** if you only run on Meta/TikTok/Apple.
3. **Roll back to AppsFlyer-only** if Layers' numbers don't match
   expectations — usually a config issue worth debugging first.

## Removing AppsFlyer [#removing-appsflyer]

Standard SDK removal — drop the AppsFlyer package, remove its init,
delete any AppsFlyer-specific manifest entries
(`INSTALL_REFERRER`, etc.). Layers continues to ingest events without
interruption.

## Caveats [#caveats]

* There is no native Layers Swift / Kotlin SDK yet, so if you currently
  call AppsFlyer from native code only, you'll need to move those call
  sites to React Native (via `@layers/react-native`) or route through a
  server-side backend using `@layers/node`.
