AppsFlyer to BigQuery: How to Sync Your Data
Sync AppsFlyer into BigQuery with Airbyte. The 90-day raw data limit, the timezone setting, organic versus non-organic streams, and quota behaviour.

Before you plan a single sync, know this: AppsFlyer only serves raw data reports for the most recent 90 days. If you set a start date further back, the connector quietly caps it at 90 days ago rather than failing. Historical raw data older than that cannot be retrieved through this pipeline at all.
That single constraint reshapes the project. If you need multi-year install history in BigQuery, this connector will not backfill it, and you should be having a different conversation about exports before you build anything.
Why don't the totals match the AppsFlyer dashboard?
This is the first thing that happens after the pipeline goes live, and it is almost never a broken sync. Start with the timezone.
The AppsFlyer source takes an optional timezone setting that defaults to UTC and accepts a tz database name such as US/Pacific. It should match the time zone in which your app's data is stored, which you will find in the app settings in the AppsFlyer console.
That field is not cosmetic. AppsFlyer aggregates by day, and a day depends on where you stand. Leave the connector on UTC while your dashboard reports in local time and every daily total shifts, with installs near midnight landing on a different date. Nothing is missing, but nothing reconciles either.
The second cause is restatement. Mobile attribution is not settled at the moment of the event, because attribution windows stay open and a conversion recorded today can be attributed to a click from days earlier. AppsFlyer's own numbers for a given day change after that day ends, so a pipeline that reads each day once and never returns captures the first version and misses every revision. Re-sync a trailing window on each run and deduplicate on the record key, so a restated day replaces the earlier version rather than sitting alongside it.
Which streams should you select?
The connector exposes two families. Eight raw data report streams cover installs, in-app events, and uninstall events, each split three ways into non-organic, organic, and retargeting variants. Ten aggregate report streams cover daily, partners, partner events, geo, and geo events, each with a retargeting counterpart.
The split into organic and non-organic streams is the thing to internalise. These are separate streams rather than a flag on one table, so a query counting total installs has to union both. Analysts who select only the installs stream will silently report non-organic numbers as if they were the whole picture.
Cursors differ by stream family. Install streams use install_time, event streams use event_time, and aggregate reports use date. All streams support both full refresh and incremental.
Four report types are not synced by this connector at all: reinstall raw data, ad revenue raw data, postbacks, and Protect360 fraud. If your analysis depends on ad revenue or fraud signals, plan for a separate route.
Configuration and quota behaviour
You need an API token (V2.0), which only an account admin can create or view. This token is tied to that admin, and AppsFlyer issues a new one if the account admin changes, at which point your connector configuration must be updated. Treat that as an operational dependency and document who holds it, because the failure arrives without warning when someone leaves.
The app ID is the platform-specific store identifier: the package name for Android, and the App Store ID prefixed with id for iOS. Getting this wrong produces an empty sync rather than an obvious error.
AppsFlyer enforces daily quotas on the Pull API, and the connector's behaviour on hitting them is worth knowing before you set a schedule. When the raw data quota is exhausted the connector waits until the quota resets at midnight UTC before retrying. Note that this reset is in UTC regardless of the timezone you configured, so an aggressive schedule can leave a sync parked for hours. The connector also honours the Retry-After header and retries on 429 and 5xx responses.
Landing the data in BigQuery
The BigQuery destination uses direct load, writing straight to final tables. Batched Standard Inserts is the default loading method and is right for AppsFlyer volumes. GCS staging exists if you want control over staging files, but it adds a bucket, an HMAC key, and a Storage Object Admin grant for usually no benefit at this scale, and buckets using customer-managed encryption keys are not supported.
Your service account needs BigQuery User and BigQuery Data Editor. Set the dataset location to match your other marketing datasets, because BigQuery queries can only reference datasets in the same physical location and the location cannot be changed after creation. Get this wrong and you cannot join attribution data against your commerce or ad-platform tables without moving one of them.
Tables are partitioned daily on the extraction timestamp and clustered on that column plus the primary keys. Note carefully what that means: the partition column records when Airbyte extracted the row, not when the install or event occurred. Analysts filtering on install_time or event_time get no partition pruning. If query cost matters, build a downstream model partitioned on the event date and point your dashboards at that instead.
Frequently asked questions
Can I backfill more than 90 days of raw data?
No. AppsFlyer serves raw data reports for the most recent 90 days only, and the connector caps an older start date at 90 days ago. Deeper history needs a different export route.
Why don't my install counts match the dashboard?
Check the timezone setting first, then check whether you are unioning the organic and non-organic streams. Selecting only the installs stream reports non-organic installs alone.
My sync suddenly started failing on authentication.
The API token is tied to the account admin who created it. If that admin changed, AppsFlyer issued a new token and the connector configuration needs updating with it.
My queries are expensive. Isn't the table partitioned?
It is partitioned on extraction time rather than event time, so filtering on install_time or event_time will not prune partitions. Model a table partitioned on the event date downstream.
Get your AppsFlyer data into BigQuery
Set the timezone to match your account, select organic and non-organic streams together, plan for restatement with a trailing re-sync, and remember the 90-day raw data ceiling. For other sources landing in the same warehouse, see our guides to Datadog to BigQuery and MongoDB to BigQuery.
Integrate with 600+ apps using Airbyte
Move data from 600+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.
