Use case

AppsFlyer reporting automation

Stop exporting AppsFlyer by hand. Opera pulls the right API at the right grain — aggregated spend, event-level conversions — applies your filters, and keeps your existing Sheet current, reconciled.

Teams that run on AppsFlyer rebuild the same export every week: pick the report, set the dates, filter the geo, download the CSV, reshape it to the Sheet's columns, paste, recompute. It works — and it quietly costs a half-day a week while inviting exactly the errors that make clients question the numbers.

The manual workflow today

  1. Open AppsFlyer, pick the app (and remember iOS and Android are separate)
  2. Set last week's dates — and hope everyone agrees what timezone 'last week' is in
  3. Export aggregate performance for spend and installs
  4. Export or query events for the conversions you actually count — purchase, purchase
  5. Filter by country and campaign prefix in the export, by hand
  6. Reshape to the report's columns, paste into the right week, recompute CAC/CPI/ROAS
  7. Sanity-check against the ad platforms and explain the gap

What breaks

  • Wrong grain — counting event rows instead of unique users inflates purchases; counting installs as customers deflates CAC's meaning entirely
  • Window mismatches — the export's attribution window doesn't match last week's, and trends jump for no real reason
  • Timezone drift — the app runs on one timezone, the analyst's export ran on another; Mondays bleed into Sundays
  • SKAN contamination — delayed, coarse iOS postbacks summed into the attributed series
  • Prefix leaks — a retargeting campaign without the agreed prefix sneaks into a UA-only report

The two APIs, used for what they're for

Most AppsFlyer reporting pain is using one export for two different jobs. Opera splits them:

Right API, right job
Master APIaggregated cost, installs, in-app events by media source / campaign / geo / date — spend, CPI, rollups
Raw Data Pull APIevent-level rows (event_name, event_time, campaign, country_code, appsflyer_id) — event-counter KPIs, deduplicated per user
SKAN reportingiOS postbacks kept in separate, labeled columns — never summed into attributed installs

Filters travel with every pull:

last full ISO week, app timezonegeo = UScampaign prefix US_event = purchasere-engagement excludedmedia_source list

What Opera does, step by step

  1. Resolves the period — last full ISO week, Monday–Sunday, in the app's configured timezone
  2. Pulls Master API spend and installs at your reporting grain
  3. Pulls Raw Data Pull API events for your KPI events, deduplicates per user, counts per campaign/day
  4. Applies geo, prefix and event filters exactly as stored for this report
  5. Pulls ad-platform spend for the same window and reconciles — variance computed, not hidden
  6. Computes CAC/CPI/ROAS by your definitions
  7. Previews the target row, checks for duplicates and overwrites, appends, posts the summary

"Update this week's report with installs, CPI and CAC by country from AppsFlyer."

On Adjust instead of AppsFlyer?

The discipline transfers. Adjust's aggregate and event-level exposures differ in names and shapes, but the load-bearing decisions are identical: aggregate pulls for spend and installs, event-level pulls deduplicated per user for KPI events, SKAN in its own lane, filters stored per report, periods resolved in the app's timezone. Opera abstracts the MMP behind the same report contract — your Sheet doesn't know or care which referee supplied the attributed column, and a future MMP migration becomes a re-mapping exercise rather than a report rebuild. What does not transfer automatically is history: numbers from two MMPs shouldn't be trended across a migration week without an annotation, which the report carries the same way it carries any definition change.

Agencies: many client apps, one discipline

Agency AppsFlyer reporting multiplies everything above by the roster: each client has its own apps (per OS), its own timezone setting, its own event taxonomy and prefixes. Opera stores each client's AppsFlyer configuration separately — app scoping, event names, filters — and runs each report under its own credentials and schedule, fully isolated. The practical win is that the discipline (dedup, SKAN separation, ISO weeks) becomes uniform across clients even though every configuration differs — which is the consistency clients experience without ever being migrated to anything.

Worked example: one US week

The request — "fill last week's US report with spend and purchase new purchases from US_ campaigns" — resolves to two pulls and one row:

Pull API Filter Result
Spend & installs Master Wk 24 · geo=US · US_ $22,400 · 11,480
Purchases Raw Data Pull + event, dedup, re-eng. excl. 1,742 events → 1,610 users

The 132-event gap between rows and users is the dedup earning its keep — re-engagement-heavy weeks would otherwise inflate purchases by 8–10%. The appended row computes CAC at $13.91 against the deduplicated count, which is the only version of that number worth trending.

iOS, SKAN and the columns that keep them honest

iOS postbacks arrive late, coarse and capped — useful signal, terrible denominator. Opera writes SKAN-modeled installs and conversions into their own labeled columns beside the attributed series, so the iOS picture is visible without ever inflating the CAC your budget decisions run on. When the iOS share of a market shifts, you see it as a mix change in labeled columns — not as a mysterious efficiency jump.

Safety checks on every run

Schema re-validated before the write; append-only into the detected anchor; the week refused if it already exists; formula columns extended, never overwritten; the full pull-and-write recorded in the audit log. If the sheet changed since last week, the run halts and tells you what moved.

Rolling it out

From manual export to scheduled run
Share the report (view access maps it) and connect AppsFlyer
Confirm the mapping — events, prefixes, geos, KPI formulas as Opera detected them
Run one previewed update in parallel with your manual export; reconcile any difference to a definition
Schedule it — Monday morning in the app's timezone, summary to your channel

See this running on your own reports.A 45-minute workflow audit maps your current process and shows exactly what Opera automates — step by step.

Frequently asked questions

Which AppsFlyer metrics can it pull?
Installs, in-app events, cost, revenue, retention and cohort metrics via the Master API; event-level conversions via the Raw Data Pull API; SKAN postbacks reported separately.
Can it count unique users for an event, not raw event rows?
Yes — event-counter KPIs are deduplicated per user (per appsflyer_id) before they enter the report. That's exactly why the Raw Data Pull API is used for them.
How does it handle iOS / SKAN?
SKAN data stays in its own labeled columns. It's visible, but it never silently inflates the attributed series your CAC is computed on.
Will it break my formulas?
No — append-only writes, formula regions protected, calculated columns extended to cover the new row.
Can it reconcile AppsFlyer against the ad platforms?
Yes, in the same run: platform-reported spend and results land beside AppsFlyer attribution with a variance column and an optional threshold flag.

See exactly what Opera would automate in your workflow.

A 45-minute teardown of how you report today: we map every step, mark what Opera automates, and send you the written spec — useful whether or not you buy.