Bring your history from AppsFlyer, Adjust or Branch, and take it out again whenever you want.
The migration importer takes an export from your current attribution platform and loads it into Measura as historical events, installs and attribution records. Your cohort charts and channel breakdowns then include the period before you switched.
Imported attributions are preserved as the source reported them. We do not re-run our matching over historical data, because the click level signals needed to do that are not in any platform’s export. Imported records carry a confidence score of zero and a written reason recording where they came from, so they are never confused with attributions Measura resolved itself.
Supported sources
custom option accepts a file whose columns already use Measura field names.| Requirement | Value |
|---|---|
| Formats | CSV or JSON (an array of objects) |
| Maximum size | 5 MB per upload |
| Maximum rows | 50,000 per upload |
| Content type | text/csv, application/json or text/plain |
| Encoding | UTF-8 |
Larger histories are imported as a sequence of uploads. Split by date range so a failed batch is easy to identify and re-run.
Export everything your platform offers. Unmapped columns are ignored rather than rejected, so a wider export costs nothing. At minimum, include the event timestamp, the event name, and at least one device identifier.
Use the raw data export. These columns are recognised automatically.
| AppsFlyer column | Measura field |
|---|---|
| Install Time | installed_at |
| Event Time | event_timestamp |
| Event Name | event_type |
| AppsFlyer ID | external_device_id |
| Advertising ID | gaid |
| Campaign | campaign_name |
| Media Source | channel |
| Attribution Type | attribution_model |
| Revenue | revenue |
| Currency | currency |
| Country Code | country_code |
| IP | ip |
| Device Type | device_model |
| OS Version | os_version |
| App Version | app_version |
| Adjust column | Measura field |
|---|---|
| installed_at | installed_at |
| event | event_type |
| gps_adid | gaid |
| network_name | channel |
| campaign_name | campaign_name |
| attribution_type | attribution_model |
| revenue_usd | revenue |
| country | country_code |
| ip_address | ip |
| device_name | device_model |
| os_name | os_name |
| os_version | os_version |
| app_version | app_version |
| Branch column | Measura field |
|---|---|
| Timestamp | event_timestamp |
| Name | event_type |
| AAID | gaid |
| Channel | channel |
| Campaign | campaign_name |
| Revenue | revenue |
| Country | country_code |
| OS | os_name |
| OS Version | os_version |
| App Version | app_version |
Branch exports carry no dedicated install time column, so the event timestamp is used for install rows.
Choosing custom applies no column translation. Your file must already use Measura field names.
[
{
"event_timestamp": "2026-05-14T08:31:02Z",
"installed_at": "2026-05-14T08:31:02Z",
"event_type": "install",
"gaid": "38400000-8cf0-11bd-b23e-10b96e40000d",
"channel": "whatsapp",
"campaign_name": "lagos-launch-may",
"attribution_model": "deterministic",
"revenue": 0,
"currency": "USD",
"device_model": "Samsung SM-A245F",
"os_name": "android",
"os_version": "14",
"app_version": "2.1.0"
}
]This is also the route for a platform we do not map natively. Rename the columns in your export tooling, then import as custom.
Source network names are translated to Measura channels. Anything unrecognised is lowercased with spaces replaced by underscores and carried through as is.
| Source value | Measura channel |
|---|---|
| Facebook Ads, facebook | meta |
| Google AdWords, google_ads | google |
| TikTok Ads | tiktok |
| Twitter Ads | twitter |
whatsapp | |
email | |
| SMS | sms |
| organic, Organic | organic |
| Source value | Measura event type |
|---|---|
| install, af_install | install |
| open, session | open |
| session_start | session_start |
| purchase, revenue, af_purchase | purchase |
| anything else | custom |
| Source value contains | Measura model |
|---|---|
| organic | organic |
| deterministic, device_id | deterministic |
| probabilistic, fingerprint | probabilistic |
| anything else | last_click |
IP addresses are truncated on import too
The developer dashboard provides this flow under Migrate. To automate it, call the three endpoints directly.
# 1. Create the job
curl -X POST "$MEASURA_HOST/functions/v1/migration-importer/start" \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"app_id":"7d2e5b1a-...","source_platform":"appsflyer"}'
# → {"job_id":"c4a9...","column_mapping":{...}}
# 2. Upload the export
curl -X POST "$MEASURA_HOST/functions/v1/migration-importer/upload?job_id=c4a9..." \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: text/csv" \
--data-binary @appsflyer-export.csv
# → {"job_id":"c4a9...","total_rows":24500,"status":"processing"}
# 3. Poll until complete
curl "$MEASURA_HOST/functions/v1/migration-importer/status?job_id=c4a9..." \
-H "Authorization: Bearer $SESSION_TOKEN"
# → {"status":"completed","processed_rows":24500,"progress_pct":100,"errors":[]}Full request and response detail is in the API Reference.
A job completes when fewer than five percent of rows produced errors. At or above that threshold the job is marked failed, on the basis that a systematic problem such as a wrong platform selection or a malformed file should not be quietly half applied.
Rows that error are listed individually in the status response with the reason, so you can correct and re-upload just those.
0 and a reason recording the source platform. Imported history is never mixed with scores Measura computed.skipped, so importing history never fires conversion notifications to advertising networks.migration-import/{platform} and a fraud score of zero.Re-uploading creates duplicates across jobs
This guide is mostly about coming in, so it is worth being just as clear about going out. You can export everything Measura holds for your account at any time, without asking us, and without a fee.
curl -X POST "$MEASURA_URL/rest/v1/rpc/export_my_account_data" \
-H "apikey: $ANON_KEY" \
-H "Authorization: Bearer $SESSION_JWT" \
-H "Content-Type: application/json" \
-d '{}' > measura-export.jsonThe export contains your apps, campaigns, short links, installs, attributions with their full confidence breakdown, raw events, fraud flags and payment records, plus a totals block so you can check nothing was truncated.
Remove the Measura dependency and the initialisation call. Nothing is left behind on the device except the local event queue, which is cleared when the app is uninstalled. There is no server call required to deactivate.
Exporting does not delete. When you have your data and have confirmed it is complete, raise a deletion request from the dashboard and the account is erased on approval. Deletion is irreversible, which is why it is a separate, deliberate step rather than a side effect of exporting.
Why this page exists
Migrating a large history, or coming from a platform not listed here? Talk to us and we will work through it with you.