Migration Guide
Bring your history from AppsFlyer, Adjust or Branch, and take it out again whenever you want.
What the importer does
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.Preparing your export
File requirements
| 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.
Which columns to include
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.
AppsFlyer column mapping
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 mapping
| 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 mapping
| 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.
Custom exports
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.
How values are normalised
Channels
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 |
Event types
| Source value | Measura event type |
|---|---|
| install, af_install | install |
| open, session | open |
| session_start | session_start |
| purchase, revenue, af_purchase | purchase |
| anything else | custom |
Attribution models
| 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
Running an import
The developer dashboard provides this flow under Migrate. To automate it, call the three endpoints directly.
- 1.Create the job. Returns a job identifier and the column mapping that will be applied, so you can confirm the mapping before committing the data.
- 2.Upload the file. Processing begins immediately, in batches of 100 rows.
- 3.Poll for status. Reports rows processed, a percentage, and any row level errors.
# 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.
Interpreting the result
Success and failure
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.
What imported records look like
- Marked as already processed, so they do not enter the live attribution queue.
- A confidence score of
0and a reason recording the source platform. Imported history is never mixed with scores Measura computed. - Postback status
skipped, so importing history never fires conversion notifications to advertising networks. - A user agent of
migration-import/{platform}and a fraud score of zero. - An idempotency key derived from the job and row position, so re-uploading the same file into the same job does not duplicate rows.
Re-uploading creates duplicates across jobs
Migrating away from Measura
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.
What to do about the SDK
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.
Deleting what we hold
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
After the import
- 1.Check your totals. Compare installs by month in the Measura dashboard against the same period in your previous platform. Small differences are expected, since deduplication and event type normalisation are not identical. Large ones are worth investigating before you switch over.
- 2.Run both platforms in parallel. Keep the old SDK alongside Measura for two to four weeks. Comparing live numbers is the only reliable way to build confidence in the switch.
- 3.Expect attribution differences. Measura declines to report matches below its confidence floor and reports them as organic instead. Your attributed share may look lower than your previous platform reported, with a corresponding rise in organic. That gap is the point rather than a defect, and the confidence score page explains the arithmetic.
- 4.Then remove the old SDK. Once the numbers reconcile and your team trusts the new figures.
Migrating a large history, or coming from a platform not listed here? Talk to us and we will work through it with you.