Google Ads to BigQuery: two ways to connect them, step by step
There are two practical ways to send Google Ads data to BigQuery: Google's BigQuery Data Transfer Service, which loads a fixed set of report tables once a day, and a connector, which lets you choose fields and reuse the same setup for other ad platforms. This guide walks through the transfer, shows what lands in BigQuery, and says when the second route is the better one.

The standard way to connect Google Ads to BigQuery is Google’s own BigQuery Data Transfer Service: you enter a Google Ads customer ID, choose a dataset, and a set of report tables is loaded once a day. The second way is a connector, which is worth it when you want to choose the fields yourself or load other ad platforms the same way.
| Data Transfer Service | Connector | |
|---|---|---|
| Built by | a third party or open source | |
| Setup | a form in the Google Cloud console | a form in the connector’s tool |
| What you get | a fixed set of report tables and views | the reports and fields you pick |
| Frequency | once every 24 hours at most | set by the tool |
| Other ad platforms | separate transfers, where Google offers one | the same setup, repeated |
Note: Fully rewritten in October 2026 against Google’s current documentation. The older route through a Google Ads script is no longer described here.
Way 1: BigQuery Data Transfer Service
Way 1: BigQuery Data Transfer Service
Everything in this section is from Google’s Google Ads transfers page, read in October 2026.
Before you start
- In Google Cloud: a project with billing, the BigQuery Data Transfer Service enabled, and a dataset to load into. Google asks for the BigQuery Admin role to create a transfer.
- In Google Ads: read access to the customer ID or manager account you will load.
Set up the transfer
- In the Google Cloud console, open BigQuery, then Data transfers, and click Create transfer.
- For Source, choose Google Ads.
- Enter the Customer ID. A manager account ID loads the accounts under it, up to 8,000 customer IDs.
- For Report type, choose Standard for Google’s set of reports, or Custom to write your own Google Ads Query Language queries.
- Optional settings:
- a comma-separated list of tables to include, or to exclude with a leading
-; - the option to include Performance Max tables, which are not exported by default;
- the refresh window, from 1 to 30 days. The default is 7.
- a comma-separated list of tables to include, or to exclude with a leading
- Choose the destination dataset and give the transfer a display name.
- Set the schedule. The most frequent setting is once every 24 hours.
- Choose the service account, if you use one, and save.
The first run starts when you create the transfer unless you set another time.
What lands in BigQuery
The transfer writes one table per report, named after the report and the customer ID, for example ads_Campaign_1234567890 and ads_CampaignBasicStats_1234567890. The tables are partitioned by date.
Two kinds of table behave differently:
- Stats tables hold metrics by day. Each run reloads the days inside the refresh window, because Google Ads keeps adjusting recent conversions and costs.
- Match tables, such as Campaign and AdGroup, hold names and settings. A snapshot is taken once a day, and the latest one is marked by
_LATEST_DATE.
That is why Google’s sample query joins them this way:
SELECT
c.customer_id,
c.campaign_name,
SUM(cs.metrics_impressions) AS impressions,
SUM(cs.metrics_interactions) AS interactions,
SUM(cs.metrics_cost_micros) / 1000000 AS cost
FROM `mydataset.ads_Campaign_1234567890` AS c
LEFT JOIN `mydataset.ads_CampaignBasicStats_1234567890` AS cs
ON c.campaign_id = cs.campaign_id
AND cs._DATA_DATE BETWEEN
DATE_ADD(CURRENT_DATE(), INTERVAL -31 DAY)
AND DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)
WHERE c._DATA_DATE = c._LATEST_DATE
GROUP BY 1, 2
ORDER BY 1, 2;
This query is adapted from Google’s page and was not run for this guide: it needs a Google Ads transfer in the project. Two details in it matter for every query on these tables:
- Cost is in micros. Divide
metrics_cost_microsby 1,000,000. - Filter the match table to its latest snapshot. Without
_DATA_DATE = _LATEST_DATE, each campaign appears once per day of history and the totals multiply. The JOIN and UNION guide explains that effect.
History and gaps
A scheduled run covers the refresh window only. For older data, or after an outage, run a backfill from the transfer’s page. Google says you can go back as far as the Google Ads data retention policy allows.
Limits to know
- Daily at most. There is no hourly Google Ads transfer.
- Performance Max needs its checkbox. With it on, Google notes that some ad group level fields are removed from the affected tables.
- Zero-impression campaigns drop out of custom reports that use segmented fields.
- The schema is Google’s. Table names, grain and columns are defined by the transfer. A custom report is the way to get anything else.
What it costs
On Google’s pricing page, transfers from Google’s own sources carry no charge for the transfer itself. You pay for the storage the tables use and for the queries you run on them; see BigQuery pricing.
Way 2: a connector
The transfer covers Google Ads well. Three situations lead teams to a connector anyway:
- You also load Facebook, TikTok, LinkedIn or Microsoft Ads. Each platform arriving through a different tool, in a different shape, on a different schedule is the real cost of ad reporting. One connector framework gives every platform the same setup and the same place to check runs.
- You want fewer, narrower tables. Picking the report and the fields keeps the dataset readable.
- Your warehouse is not BigQuery. The Data Transfer Service loads only into BigQuery.
OWOX Data Marts includes an open-source Google Ads connector. You create a Data Mart with the Connector definition type, choose Google Ads, connect your account, pick the fields and set a trigger. The data lands raw in your own warehouse; OWOX Data Marts does not transform it. The full walkthrough, with screenshots of each step, is in the Google Ads to BigQuery connector guide.
OWOX Data Marts
See your first report built in real time. 15 minutes.
- Connect your data warehouse
- Pick your metrics
- Get a live Google Sheets report
In the time it takes to write a ticket. Then imagine never writing that ticket again.
Book a DemoWe'll use your actual use case
After the data is in BigQuery
Raw Google Ads tables answer Google Ads questions. The questions people actually ask cross sources: spend against revenue, Google against Meta, cost per order by channel.
- Blend ad platforms into one spend table with
UNION ALL, after renaming columns to a common set. - Join spend to conversions from your website data. The GA4 to BigQuery guide covers that export.
- Deliver the result where the team reads it. The steps for a spreadsheet are in how to connect BigQuery to Google Sheets.
Published once as a Data Mart in OWOX Data Marts, that blended query becomes the one definition of spend that the sheet, the and the weekly email all read.
Troubleshooting
- The transfer fails with a permission error. Check both sides: BigQuery Admin on the project, and read access to the customer ID in Google Ads for the account that created the transfer.
- Numbers are higher than in Google Ads. A match table was joined without the latest-snapshot filter.
- Recent days keep changing. That is the refresh window doing its job. Lengthen it, up to 30 days, if your conversions arrive late.
- Performance Max campaigns are missing. Turn on the Performance Max option in the transfer settings.
Turn your data into decisions.
Governed data marts give you the clean foundation ML needs to actually work.
- No AI hallucinations
- Analyst-governed definitions
- Every number traces to SQL



