Skip to content
Streamkap
Esc
↑↓navigate↵open⌘Jpreview
On this page

Google Ads

Stream Google Ads campaigns, ads, criteria, assets and daily performance reports into Streamkap with a service account or an OAuth refresh token.

The Google Ads source reads one Google Ads account, several, or every client account under a manager, and writes each selected resource to its own topic, source_<id>.google_ads.<resource>.

Prerequisites

  • A Google Ads account, or a manager account with client accounts.
  • A Google Cloud project where you can enable APIs and create OAuth clients or service accounts.
  • One of:
    • a Google user with at least read-only access to the accounts and 2-Step Verification turned on, or
    • a service account you can add as a user of the accounts.

No developer token is needed. Google stopped using them on 9 September 2026, and API access now belongs to the Cloud project that owns the OAuth client or service account.

Google Setup

1. Enable the Google Ads API

In the Google Cloud console, select your project and enable the Google Ads API under APIs & Services → Library.

2. Get Production Access

A new project has Test access, which reads test accounts only. On the project’s Google Ads API Overview page, apply for:

  • Explorer: 2,880 operations a day against production accounts.
  • Basic: 15,000 operations a day.

The budget belongs to the Cloud project and is shared by every tool that uses it. See Quota.

3. Create the Credential

  • Under APIs & Services → OAuth consent screen, set the consent screen to In production, or use the Internal user type. A consent screen left in Testing issues refresh tokens that expire after 7 days.
  • Under APIs & Services → Credentials, create an OAuth client ID of type Web application.
  • Copy the Client ID and Client secret.

Then mint a refresh token with this same client for the https://www.googleapis.com/auth/adwords scope with offline access. Google keeps at most 100 refresh tokens per user and client and silently revokes the oldest.

A service account needs no consent screen and has no 7-day Testing expiry or 100-token limit (Google’s guide).

  • Under IAM & Admin → Service accounts, create a service account (it needs no Cloud role), then choose Keys → Add key → Create new key → JSON and keep the file.
  • In Google Ads, open Admin → Access and security → Users and add the service account’s email (client_email in the key file) with read-only access. No domain-wide delegation is needed.
  • A service account can be added to at most 20 Google Ads accounts. For more, add it to a manager account and set Login customer ID (manager) to that manager.

4. Find Your Customer IDs

The customer ID is the ten-digit number at the top right of Google Ads, such as 123-456-7890. Dashes are optional. If you reach the account through a manager account, also note the manager’s customer ID.

Streamkap Setup

1. Create the Source

2. Connection Settings (Auth Tab)

  • Source name: A unique name for this source.
  • Authentication: Service account (default) or Paste a refresh token.
  • OAuth client ID, OAuth client secret and Refresh token (Paste a refresh token): From your OAuth client, and a token minted with it.
  • Service account key (Service account): The whole JSON key file.
  • Customer ID: The account to sync. Once the credentials are entered, the field lists the accounts they reach by name; pick one or type the ID. For a manager account, turn on Include client accounts.
  • Additional customer IDs (optional): More accounts to read with the same credentials. See Several Accounts.
  • Login customer ID (manager) (optional): The manager account through which the Google user or service account reaches these accounts. Leave it empty for direct access.
  • Include client accounts (default off): Treat Customer ID as a manager and sync every enabled client account under it, including clients added later.

Test connection and Test access work as described in API sources. For Google Ads:

  • Each search costs one operation of your project’s daily budget. The test checks at most the first 10 accounts.
  • A report is read for yesterday in each account’s time zone, with its row count. A report with more than 25,000 rows a day is blocked; one with more rows than restatement can track gets a warning (see Restatement).
  • A custom query runs for one day, which Google validates in full.
  • Warnings that do not block saving: a test account (it serves no ads), a manager with no enabled client accounts, or an account the user does not reach directly (set Login customer ID (manager)).

3. Settings Tab

Google Ads source Settings step with the resource presets, the Resources list, Custom queries, Conversion window and API version

  • Resources: The objects and reports to sync. The ten defaults are marked in Supported Resources and use about 360 operations a day per account. Select custom_<name> for each query in Custom queries. Presets under Add a preset:
    • Overview: the ten defaults.
    • Search: Overview plus keyword_view, search_term_view and ad_group_ad_performance.
    • Audience and geography: campaign, ad_group, customer, geographic_view, user_location_view, age_range_view, gender_view and ad_group_audience_view.
    • Performance Max and assets: campaign, customer, asset_group, asset, campaign_asset, ad_group_asset, asset_set and campaign_asset_set.
  • Custom queries (optional): GAQL queries as a JSON list of {name, query}. See Custom Queries.
  • Conversion window (days) (default 30, max 90): How many days back reports are re-read for late conversions. Set it to the longest click-through conversion window of your conversion actions.
  • API version: v25, the only version.
  • Backfill start date: Last two years (change history 29 days; clicks, calls and leads 90 days) or Specific start date. See Backfill and API sources.

4. Review and Create

Check the summary and click Create. Then send the topics to a destination: see Send topics to a destination.

Editing the Source

  • Credentials: click Replace on the client secret, refresh token or service account key and save. If you change OAuth client ID, enter the new client’s secret and a refresh token minted with it in the same save.
  • Custom queries: a synced query cannot change under the same name, because its fields define the columns and the id. The poll fails with that fix. Add the changed query under a new name.

Everything else follows Editing an API source.

Supported Resources

58 resources, plus your custom queries. Every resource reads every account of the source into one topic.

Entities

Read whole on the first poll, then only what Google’s change_status lists as changed, every 5 minutes.

Resource What it holds Default
campaign Campaigns: status, channel, bidding, budget, network and geo settings, dates Yes
ad_group Ad groups: status, type, bids Yes
ad_group_ad Ads: type, text, final URLs, policy summary Yes
ad_group_criterion Keywords, audiences, placements and other ad-group targeting Yes
campaign_criterion Campaign targeting: locations, languages, devices, schedules, negatives Yes
campaign_budget Budgets: amount, period, delivery method, shared flag Yes
ad_group_bid_modifier Ad-group bid adjustments
asset, asset_group, asset_set Assets, Performance Max asset groups, asset sets
ad_group_asset, campaign_asset, customer_asset, campaign_asset_set Links between assets and ad groups, campaigns or the account
shared_set, campaign_shared_set Shared negative keyword and placement lists, and the campaigns using them

Daily Re-reads

Read whole once a day. New and changed rows are sent; a row missing from a complete read is deleted.

Resource What it holds Default
customer The account: name, currency, time zone, status, auto-tagging, tracking template Yes
customer_client The accounts under a manager
label, customer_label, campaign_label, ad_group_label, ad_group_ad_label, ad_group_criterion_label Labels and what they are attached to
bidding_strategy Portfolio bidding strategies
campaign_bid_modifier Campaign bid adjustments
audience, user_interest Audiences, and Google’s interest categories
local_services_lead Local Services leads
geo_target_constant Google’s location list, read weekly

Logs

Read hourly by their own timestamp. Each row is written once.

Resource What it holds
change_event Who changed what and when, with old and new values. Google keeps 30 days.
call_view Calls: caller area, duration, status
lead_form_submission_data Lead-form submissions
local_services_lead_conversation Messages and calls on Local Services leads

Reports

One row per day per key, in the account’s time zone, re-read hourly for the conversion window. Each report selects the standard metrics its resource allows: impressions, clicks, cost, conversions and value, all conversions, view-through conversions, interactions, video views, CTR, average CPC and CPM, search impression share and Active View metrics.

Resource One row per day per Default
account_performance account Yes
campaign_performance campaign Yes
ad_group_performance ad group Yes
account_performance_by_network_device, campaign_performance_by_network_device, ad_group_performance_by_network_device …, network and device
account_performance_hourly, campaign_performance_hourly, ad_group_performance_hourly …, and hour
campaign_budget_performance budget
ad_group_ad_performance ad, network and device
keyword_view keyword
search_term_view search term and ad group
display_keyword_view, topic_view Display keyword or topic
geographic_view, user_location_view, location_view country and location type, user location, or targeted location
shopping_performance_view product, channel and device
age_range_view, gender_view age range or gender, and device
ad_group_audience_view audience, network and device
landing_page_view landing page
click_view click (GCLID). Google serves one day per query and keeps 90 days.

change_status is not a topic: it drives the entities. Select change_event for the change history.

Custom Queries

Custom queries is a JSON list of {name, query}. Select each as custom_<name>. Google’s Query Builder helps write them.

[
  {"name": "campaign_devices", "query": "SELECT campaign.id, campaign.name, segments.device, metrics.clicks, metrics.cost_micros FROM campaign WHERE campaign.status = 'ENABLED'"}
]
  • Write SELECT, FROM and an optional WHERE. ORDER BY, LIMIT, PARAMETERS and date filters are refused: Streamkap sets them.
  • A query with metrics is a report: Streamkap adds segments.date and re-reads it for the conversion window. Its FROM must allow segments.date.
  • A query without metrics is re-read whole daily, like the daily re-reads.
  • FROM change_status, change_event and click_view are refused; use their resources.
  • Each query is checked on save against Google’s field list for the API version: fields must exist, be selectable (and filterable where filtered) and be compatible with the FROM resource.

Behavior & Limits

Record Columns

  • Column names are the GAQL field names with . replaced by _, such as campaign_id and metrics_clicks. A name over 63 characters keeps its first 54 characters plus a short hash.
  • id is the Kafka key. For an entity, daily re-read or log it is the resource name, such as customers/1234567890/campaigns/2001. For a report it is the resource name, then any segmenting resource names, the date and each other selected segment, joined with |, such as customers/1234567890/campaigns/2001|2026-09-24|MOBILE.
  • customer_id names the account the row came from.
  • Entities also carry streamkap_changed_at (UTC), change_status_last_change_date_time (Google’s time, in the account’s time zone) and change_status_resource_status.
  • 64-bit numbers (ids, cost_micros, impressions, clicks) are integers, other metrics doubles, enums their names, dates YYYY-MM-DD, nested messages and lists JSON text. A field Google omits takes its default (0, false, empty string or UNSPECIFIED).
  • Money is in micros of the account’s currency: cost_micros 1,500,000 is 1.50.

Backfill

The Backfill start date bounds each resource’s first sync only:

  • Reports start on that date, or two years back by default, never more than 37 months back. click_view reads at most 90 days.
  • Logs start on that date, or 90 days back by default. change_event reads at most 29 days.
  • Entities and daily re-reads are always read whole.

Restatement

Google keeps attributing conversions to past clicks. Each hourly poll re-reads the last Conversion window (days) of every report and re-sends rows whose values changed, under the same id. Set the destination to upsert on id, and never sum a report topic.

  • Streamkap tracks 10,000 report rows across the window. A report with more than 10,000 ÷ (conversion window + 1) rows a day (about 320 at 30 days, 110 at 90) re-sends some rows of its oldest days on every poll as duplicate upserts.
  • A row Google stops serving, such as a day whose metrics fell to zero, keeps its last values.

Entity Changes and Removals

Each poll reads change_status from where the last one stopped, minus an hour to cover daylight-saving changes, and refetches each changed entity whole. Google lists a change up to three minutes after it happens.

Every entity is also re-read whole every 7 days, to catch changes Google makes itself that change_status may not list, and after a pause longer than 88 days (change_status keeps 90).

A removed campaign, ad group, ad or criterion arrives as an upsert with status REMOVED, not as a delete, so its spend in the reports keeps a matching row. One Google no longer returns arrives as its key, REMOVED and the change columns.

Several Accounts

Additional customer IDs and Include client accounts add accounts to Customer ID. Client accounts under a manager are looked up again every hour. Every row carries its customer_id, and each account’s reports use its own time zone.

An account added after a resource has synced is read from that resource’s current position. Reset the source to backfill its history.

When Google refuses one account (no access, not enabled, or a metric unavailable to it), that account is skipped with a warning, its existing rows stay, and each poll retries it. When the source reads one account, or every account is refused, the refusal applies to the whole source; a metric refused on every account pauses only that report.

Quota

Google counts operations per Cloud project over a rolling 24 hours. Each search is one operation; extra pages are free; a refused request still counts. The default selection costs about 360 a day per account.

  • Project budget spent: the source shows Throttled until Google’s retry delay, or an hour, then resumes.
  • One account’s budget spent: that account pauses and the others continue. A report advances only as far as the paused account can catch up.
  • Short-term rate limit: the request waits Google’s retry delay, up to a minute, and retries.

To use fewer operations, select fewer resources or apply for Basic access.

Cadence

  • Entities: every 5 minutes.
  • Reports and logs: hourly.
  • Daily re-reads: daily; geo_target_constant weekly.

Troubleshooting

"Google rejected the refresh token …" or "Google rejected the OAuth client or refresh token …"

The token was revoked, unused for six months, dropped past Google’s 100-token limit, or issued by a consent screen in Testing, whose tokens expire after 7 days.

Resolution: Set the consent screen to In production, or use the Internal user type. Then mint a new refresh token with the same client, paste it with Replace on the Auth tab, and save.

"… has no access to Google Ads" or "Google requires 2-Step Verification …"

The Google user behind the token cannot sign in to Google Ads, or has not turned on 2-Step Verification, which the manager account enforces.

Resolution: Give the user access or turn on 2-Step Verification, then connect again or paste a new token minted by that user.

"The Google Cloud project that owns this OAuth client (or service account) has only Test access"

Resolution: Apply for Explorer or Basic access on the project’s Google Ads API Overview page. See Get Production Access.

"Account … is a manager account"

A manager has no campaigns or metrics of its own.

Resolution: Put a client account in Customer ID and the manager in Login customer ID (manager), or turn on Include client accounts.

"Google rejected the service account key"

The key or its service account was deleted or disabled, or the pasted text is not the key file.

Resolution: Create a new JSON key under IAM & Admin → Service accounts → Keys → Add key, paste it with Replace, and save.

"Login customer ID … does not manage account …"

Resolution: Set it to the manager above the account, or clear it for direct access.

Numbers differ from Google Ads

Recent days are still being revised for conversions. Compare a day older than the conversion window, in the account’s time zone, and compare the same conversion columns (metrics_conversions or metrics_all_conversions).