Connect Retool to Google Ads by creating a REST API Resource using Google Ads API OAuth 2.0 with a developer token and client credentials. Build search campaign performance dashboards using GAQL (Google Ads Query Language) to query campaign metrics, keyword-level data, and ad group analytics — giving PPC teams faster reporting than Google Ads' native interface.
| Fact | Value |
|---|---|
| Tool | Google Ads |
| Category | Marketing |
| Method | REST API Resource |
| Difficulty | Advanced |
| Time required | 45 minutes |
| Last updated | April 2026 |
Build a Google Ads Reporting and Management Panel in Retool
Google Ads' native interface provides powerful but fragmented reporting — campaign data is in one view, keyword data in another, and comparing performance across multiple client accounts requires switching between accounts. PPC managers and marketing analysts need cross-account dashboards: all campaigns sorted by ROAS in one table, keyword-level click share and quality score for all active ad groups, budget utilization tracking showing which campaigns are on pace to overspend or underspend this month. Retool lets you build these custom views against the Google Ads API.
The Google Ads API uses GAQL — Google Ads Query Language — a SQL-like syntax specifically designed for ad performance reporting. Queries select metrics and dimensions from Google Ads' resource types: campaign, ad_group, ad_group_keyword_view, search_term_view, and many others. All API requests are made to a per-account HTTPS endpoint with POST to /googleads/v17/customers/{customer_id}/googleAds:search.
The most valuable Retool use case for Google Ads is a keyword performance command center for PPC managers. They can see keyword-level impressions, clicks, CTR, average CPC, Quality Score, and conversion rate across all campaigns in a single sortable Table — with the ability to filter to specific campaigns, ad groups, or match types. Anomalies (sudden CTR drops, Quality Score declines) that would take minutes to find in Google Ads' interface become immediately visible.
Integration method
Google Ads connects to Retool via a REST API Resource using Google Ads API OAuth 2.0 with a developer token. Authentication requires an OAuth 2.0 Bearer token (obtained via Google's authorization server), a developer token (from Google Ads API Center), and optionally a login-customer-id header for Manager Account (MCC) access. All API calls use Google Ads Query Language (GAQL) for structured reporting. Retool proxies all requests server-side.
Prerequisites
- A Google Ads account with active campaigns (test accounts work for API setup but have no real data)
- A Google Ads API developer token (apply at https://ads.google.com/nav/selectaccount then API Center — basic access level is sufficient for most reporting use cases)
- A Google Cloud project with the Google Ads API enabled and OAuth 2.0 client credentials (client ID and client secret)
- An OAuth 2.0 refresh token obtained by authorizing the Google Ads API for your Google account
- Your Google Ads customer ID (the 10-digit ID in the format XXX-XXX-XXXX visible in Google Ads top right)
Step-by-step guide
Obtain Google Ads API developer token and OAuth credentials
The Google Ads API requires three authentication components: a developer token, OAuth 2.0 client credentials, and a user OAuth token. Step 1 — Developer token: Log into your Google Ads manager account (MCC). Navigate to Tools & Settings → Setup → API Center. Apply for API access if you haven't already. A test developer token is available immediately for testing against test accounts. Production access (real account data) requires applying for basic or standard access (approval takes 1–5 business days). Step 2 — Google Cloud OAuth credentials: Go to https://console.cloud.google.com. Create a project or use an existing one. Enable the 'Google Ads API' in APIs & Services → Library. Navigate to APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID. Select Web Application. Add https://oauth2.googleapis.com and your Retool URL as authorized redirect URIs. Download the client JSON to get your client_id and client_secret. Step 3 — OAuth refresh token: Use Google's OAuth 2.0 playground (https://developers.google.com/oauthplayground) or a local script to authorize the Google Ads API scope (https://www.googleapis.com/auth/adwords) for your Google account. Exchange the authorization code for an access token and refresh token. Copy the refresh_token. Store all credentials in Retool Configuration Variables: GOOGLE_ADS_DEVELOPER_TOKEN (marked as secret), GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET (secret), GOOGLE_ADS_REFRESH_TOKEN (secret), and GOOGLE_ADS_CUSTOMER_ID.
Pro tip: Google Ads API test developer tokens can only query test accounts (those created specifically for API testing in your MCC). To query real campaign data, your developer token needs basic or standard access — apply for this in Google Ads API Center before building your Retool dashboard.
Expected result: You have all four Google Ads API credentials stored in Retool Configuration Variables: developer token, client ID, client secret, refresh token, and customer ID.
Set up token refresh and create the Google Ads REST API Resource
Google Ads OAuth 2.0 access tokens expire after 1 hour. You need a mechanism to refresh them before building queries. Create a Retool JavaScript query called refreshGoogleAdsToken (set to run on page load): POST https://oauth2.googleapis.com/token with body: grant_type=refresh_token&client_id={{ retoolContext.configVars.GOOGLE_ADS_CLIENT_ID }}&client_secret={{ retoolContext.configVars.GOOGLE_ADS_CLIENT_SECRET }}&refresh_token={{ retoolContext.configVars.GOOGLE_ADS_REFRESH_TOKEN }} This returns a fresh access_token valid for 1 hour. Store this in a Retool variable: setVariable('googleAdsAccessToken', response.access_token). Now create the REST API Resource: Resources tab → Add Resource → REST API. Name: Google Ads API Base URL: https://googleads.googleapis.com Authentication: Bearer Token → {{ googleAdsAccessToken.value }} (references the variable set by the token refresh query). Add headers: - developer-token: {{ retoolContext.configVars.GOOGLE_ADS_DEVELOPER_TOKEN }} - login-customer-id: {{ retoolContext.configVars.GOOGLE_ADS_MANAGER_ACCOUNT_ID }} (only needed if accessing via MCC — omit if accessing a standalone account directly) Click Create Resource.
1// JavaScript query: refreshGoogleAdsToken2// POST https://oauth2.googleapis.com/token3// (Use a separate REST API Resource pointed at oauth2.googleapis.com for this query)4const response = await fetch('https://oauth2.googleapis.com/token', {5 method: 'POST',6 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },7 body: [8 `grant_type=refresh_token`,9 `client_id=${retoolContext.configVars.GOOGLE_ADS_CLIENT_ID}`,10 `client_secret=${retoolContext.configVars.GOOGLE_ADS_CLIENT_SECRET}`,11 `refresh_token=${retoolContext.configVars.GOOGLE_ADS_REFRESH_TOKEN}`12 ].join('&')13});14const data = await response.json();15return data.access_token;Pro tip: Because Retool JavaScript queries run in a sandboxed browser context, the fetch() call for token refresh goes directly from the browser. For production security, move token refresh to a Retool Workflow that runs server-side and updates the GOOGLE_ADS_ACCESS_TOKEN configuration variable on a schedule.
Expected result: The Google Ads REST API Resource is created with the Bearer token referencing your refreshed access token. The developer-token header is configured. The resource is ready for GAQL queries.
Write GAQL queries for campaign and keyword performance
Google Ads API uses POST requests with GAQL query in the request body. All reporting queries go to: POST /v17/customers/{{ retoolContext.configVars.GOOGLE_ADS_CUSTOMER_ID }}/googleAds:search The request body is a JSON object with a single query field containing the GAQL string. Create a getCampaignPerformance query: POST /v17/customers/{customerId}/googleAds:search with body: { "query": "SELECT campaign.id, campaign.name, campaign.status, campaign.advertising_channel_type, metrics.impressions, metrics.clicks, metrics.ctr, metrics.average_cpc, metrics.conversions, metrics.cost_micros, metrics.roas FROM campaign WHERE campaign.status = 'ENABLED' AND segments.date DURING LAST_30_DAYS ORDER BY metrics.cost_micros DESC LIMIT 50" } GAQL key concepts: - Resources: campaign, ad_group, keyword_view, search_term_view, campaign_budget - Metrics: metrics.impressions, metrics.clicks, metrics.ctr, metrics.average_cpc, metrics.cost_micros (divide by 1,000,000 to get dollars), metrics.conversions, metrics.roas - Segments: segments.date, segments.device, segments.day_of_week - Date filters: WHERE segments.date DURING LAST_7_DAYS (also: LAST_30_DAYS, THIS_MONTH, LAST_MONTH) - Status filters: WHERE campaign.status = 'ENABLED' (values: ENABLED, PAUSED, REMOVED) Create a getKeywordPerformance query with a GAQL query targeting the ad_group_criterion resource with ad_group_criterion.type = 'KEYWORD'.
1// GAQL query for keyword performance2// POST /v17/customers/{customerId}/googleAds:search3{4 "query": "SELECT ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, ad_group_criterion.quality_info.quality_score, ad_group.name, campaign.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.average_cpc, metrics.conversions, metrics.cost_micros FROM ad_group_criterion WHERE ad_group_criterion.type = 'KEYWORD' AND ad_group_criterion.status = 'ENABLED' AND segments.date DURING LAST_30_DAYS ORDER BY metrics.impressions DESC LIMIT 200"5}Pro tip: Google Ads API returns cost in micros (millionths of the currency unit). Divide metrics.cost_micros by 1,000,000 to get the dollar amount. CPC is already in the currency unit (not micros) when returned as metrics.average_cpc.
Expected result: The getCampaignPerformance query returns an array of campaign objects with metrics. The getKeywordPerformance query returns keywords with Quality Scores and performance metrics.
Transform GAQL responses and build the campaign dashboard UI
Google Ads API GAQL responses have a nested structure. Each row in the response is an object with nested resource and metrics objects. Create a transformer to flatten this for the Table component. The response format from GAQL is: { results: [ { campaign: { id, name, status }, metrics: { impressions, clicks, ctr, average_cpc, cost_micros, conversions } }, ... ] } Create a campaignTransformer to flatten and compute derived metrics. Then bind to a Table component. For the keyword Quality Score dashboard, create a separate Table with color-coded Quality Score badges using Retool's Table column formatting: set the quality_score column to tag/badge type with rules — red for 1-4, yellow for 5-6, green for 7-10. Add summary Stat components above the Table: - Total Spend: sum of all campaign cost values - Total Clicks: sum of clicks - Average CTR: weighted average by impressions - Total Conversions: sum of conversions For a Chart comparing campaigns by spend vs. ROAS, use Retool's Chart component (Plotly.js). Create a scatter plot with x = ROAS and y = spend, with bubble size representing impressions. This visualizes the efficiency/scale relationship across all campaigns at a glance.
1// Transformer for GAQL campaign response2const results = data?.results || [];3return results.map(row => {4 const campaign = row.campaign || {};5 const metrics = row.metrics || {};6 const budget = row.campaignBudget || {};78 const costDollars = (metrics.costMicros || 0) / 1000000;9 const ctr = parseFloat(metrics.ctr || 0) * 100;10 const avgCpc = (metrics.averageCpc || 0) / 1000000;11 const roas = metrics.conversionsValue > 012 ? (metrics.conversionsValue / costDollars).toFixed(2)13 : '0.00';1415 return {16 id: campaign.id,17 name: campaign.name,18 status: campaign.status,19 channel: campaign.advertisingChannelType || '',20 impressions: parseInt(metrics.impressions || 0).toLocaleString(),21 clicks: parseInt(metrics.clicks || 0).toLocaleString(),22 ctr: `${ctr.toFixed(2)}%`,23 avg_cpc: `$${avgCpc.toFixed(2)}`,24 spend: `$${costDollars.toFixed(2)}`,25 spend_raw: costDollars,26 conversions: parseFloat(metrics.conversions || 0).toFixed(1),27 roas: roas,28 conv_rate: metrics.clicks > 029 ? `${((metrics.conversions / metrics.clicks) * 100).toFixed(2)}%`30 : '0.00%'31 };32});Pro tip: Google Ads API returns metric values as strings in the JSON response, not numbers — always use parseInt() or parseFloat() when doing arithmetic on metrics values. The costMicros field in GAQL responses uses camelCase (not snake_case), unlike the GAQL query syntax.
Expected result: The campaigns Table shows all active campaigns with spend, CTR, and ROAS metrics formatted as currency and percentages. Quality Score badges are color-coded in the keywords Table.
Build the search term report and multi-account support
Create a getSearchTerms query: POST /v17/customers/{customerId}/googleAds:search with GAQL: { "query": "SELECT search_term_view.search_term, campaign.name, ad_group.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.cost_micros, metrics.conversions FROM search_term_view WHERE segments.date DURING LAST_30_DAYS AND metrics.impressions > 10 ORDER BY metrics.cost_micros DESC LIMIT 500" } Filter the search term results in a transformer to identify 'waste' terms: high cost (> $5) with zero conversions. Display these in a separate 'Negative Keywords Candidates' Table to help PPC managers identify irrelevant queries. For multi-account support (MCC/manager accounts), create a getAccessibleCustomers query: GET /v17/customers:listAccessibleCustomers. This returns all Google Ads accounts accessible to the authenticated user. Build a customer Select component and dynamically replace the customer ID in all query paths based on the selection. For the budget pacing calculation, fetch campaign budget data: SELECT campaign.name, campaign_budget.amount_micros FROM campaign WHERE campaign.status = 'ENABLED'. Compute pacing status in a transformer using the current day of month and total days in the current month. For PPC teams managing multiple Google Ads accounts across complex agency or enterprise setups, combining GAQL reporting with automated budget alerts, bid change tracking, and internal dashboard distribution, RapidDev's team can help architect the complete Retool solution.
1// Transformer: identify negative keyword candidates2const terms = data?.results || [];3const formatted = terms.map(row => ({4 term: row.searchTermView?.searchTerm || '',5 campaign: row.campaign?.name || '',6 ad_group: row.adGroup?.name || '',7 impressions: parseInt(row.metrics?.impressions || 0),8 clicks: parseInt(row.metrics?.clicks || 0),9 cost: (row.metrics?.costMicros || 0) / 1000000,10 conversions: parseFloat(row.metrics?.conversions || 0)11}));1213// Flag waste: cost > $2, conversions = 0, impressions > 2014const negativeCandidates = formatted.filter(t =>15 t.cost > 2 && t.conversions === 0 && t.impressions > 2016);1718return {19 all_terms: formatted,20 negative_candidates: negativeCandidates.sort((a, b) => b.cost - a.cost),21 total_waste: negativeCandidates.reduce((sum, t) => sum + t.cost, 0).toFixed(2)22};Pro tip: Google Ads API rate limits are per developer token, not per account. If you query multiple accounts in parallel from the same developer token, you may hit rate limits faster than expected. For multi-account dashboards, consider sequential queries with a short delay between accounts.
Expected result: The search terms Table shows all queries triggering your ads with a negative keyword candidates tab pre-filtered to high-cost, zero-conversion terms. Multi-account switching works via the customer Select dropdown.
Common use cases
Build a keyword performance and Quality Score dashboard
Create a Retool dashboard showing all active keywords across all campaigns with impressions, clicks, CTR, average CPC, Quality Score, and conversion rate. PPC managers can sort by Quality Score to find underperforming keywords, filter to specific campaigns, and identify keywords with high impressions but low CTR that need ad copy improvement.
Build a Retool keyword performance panel for Google Ads. Show all enabled keywords with: keyword text, match type, campaign, ad group, impressions, clicks, CTR, average CPC, Quality Score (1-10), conversions, and conversion rate. Sort by Quality Score ascending to surface low-quality keywords first. Add campaign filter. Color-code Quality Score: red for 1-4, yellow for 5-6, green for 7-10.
Copy this prompt to try it in Retool
Build a campaign budget utilization and pacing dashboard
Build a Retool panel showing all active Google Ads campaigns with daily budget, spend today, month-to-date spend, budget utilization percentage, and pacing status. Marketing managers can see which campaigns are on track, overpacing (at risk of exhausting budget early), or underpacing (won't spend the full budget by month end).
Build a Retool Google Ads budget pacing dashboard. Show all campaigns with: campaign name, status, daily budget, today's spend, MTD spend, % of monthly budget used, and pacing status (On Track / Overpacing / Underpacing). Compute pacing as: expected spend = (days elapsed / days in month) × monthly budget. If actual > expected × 1.1, show Overpacing in red. Include a total row showing combined budget and spend.
Copy this prompt to try it in Retool
Build a search term report for negative keyword discovery
Create a Retool tool showing the Google Ads search terms that triggered your ads — including terms that are not yet in your keyword list. Identify irrelevant search terms with impressions but no conversions that should be added as negative keywords to reduce wasted spend.
Build a Retool search terms analysis panel. Fetch the last 30 days of search terms from Google Ads. Show: search term, campaign, ad group, impressions, clicks, CTR, cost, conversions. Filter to terms with: cost > $5 AND conversions = 0. Sort by cost descending. Add an 'Add as Negative' button that marks the selected search term for negative keyword review. Export button for the negative keyword list.
Copy this prompt to try it in Retool
Troubleshooting
PERMISSION_DENIED error with 'Developer token does not have permission to access' message
Cause: A test developer token can only query test accounts, not real Google Ads accounts. Attempting to query a live account with a test token results in a permission denied error.
Solution: Apply for basic access to the Google Ads API in your Google Ads account → Tools & Settings → API Center. Basic access allows querying real account data for production use. Approval typically takes 1–5 business days. In the meantime, create a test Google Ads account (visible in your MCC) to test your Retool integration with real API responses.
401 Unauthorized after the dashboard has been open for a while
Cause: Google Ads OAuth 2.0 access tokens expire after 1 hour. The token generated on page load becomes invalid after this period, causing all subsequent API calls to return 401.
Solution: Add a Refresh Token button to your Retool dashboard that re-runs the refreshGoogleAdsToken query and updates the access token variable. For an automated solution, set the refreshGoogleAdsToken query to run on a 50-minute timer using Retool's query periodic trigger setting. This keeps the token fresh without requiring user interaction.
1// Set query to auto-refresh:2// In query settings, enable 'Run automatically'3// Set interval to 3000000 ms (50 minutes)GAQL query returns 'INVALID_ARGUMENT' with 'Cannot select segment X with resource Y' error
Cause: Some GAQL dimensions and segments are incompatible with certain resource types. Google Ads API enforces resource compatibility rules — not all fields can be combined in a single query.
Solution: Check Google's GAQL resource compatibility tables in the official documentation at https://developers.google.com/google-ads/api/fields/. For common issues: segments.device cannot be combined with campaign_budget resource; metrics.search_impression_share requires campaign or ad_group resources, not keyword_view. Split incompatible fields into separate queries if needed.
1// GAQL compatibility example:2// Valid: SELECT campaign.name, metrics.clicks FROM campaign3// Invalid: SELECT campaign_budget.amount_micros, metrics.clicks FROM campaign4// (budget fields and metrics cannot be selected from the same resource)GAQL metrics return zero values for date ranges despite campaigns running
Cause: The customer ID in the API endpoint path may belong to a manager account (MCC) rather than a leaf customer account. Manager accounts do not have performance metrics directly — you must query leaf account IDs.
Solution: Verify you are querying a leaf customer account (one that runs actual campaigns) rather than a manager account. Use GET /v17/customers:listAccessibleCustomers to see all accessible accounts. Manager account IDs (MCCs) appear in the list but have no direct metrics. Use the leaf account customer IDs for performance queries.
1// Correct endpoint for leaf account:2// POST /v17/customers/LEAF_CUSTOMER_ID/googleAds:search3// NOT: POST /v17/customers/MCC_MANAGER_ID/googleAds:searchBest practices
- Store all Google Ads API credentials (developer token, client ID, client secret, refresh token) in Retool Configuration Variables marked as secret — never hardcode them in resource configurations or JavaScript queries.
- Implement OAuth 2.0 token refresh on a 50-minute schedule using a Retool Workflow — Google Ads access tokens expire after 1 hour and stale tokens cause dashboard failures during active sessions.
- Always use the segments.date DURING LAST_30_DAYS or explicit date range filters in GAQL queries — queries without date segments return all-time totals which are slower and usually not what dashboards need.
- Limit GAQL results to 1000 rows maximum and use OFFSET for pagination — Google Ads API has a default result limit and very large queries can time out on accounts with many campaigns or keywords.
- Divide metrics.cost_micros by 1,000,000 in your transformer to convert to dollar amounts — Google Ads API returns all monetary values in micros (millionths) of the account currency, which is easy to overlook.
- For multi-account MCC setups, always add the login-customer-id header pointing to the MCC ID and query individual leaf account IDs in the endpoint path — omitting the login-customer-id header causes 401 errors when accessing accounts through a manager.
- Cache campaign and ad group reference data (IDs and names) for 10 minutes — this data changes infrequently and repeated lookups waste quota on stable reference data.
- Apply for basic access to the Google Ads API before going to production — a test developer token blocks access to real account data and the approval process for basic access requires a few business days.
Alternatives
Facebook Ads uses Graph API and System User tokens rather than developer tokens — choose it for social media advertising analytics where audience targeting and creative performance matter more than search keyword metrics.
Bing Ads uses Azure AD OAuth and async report generation — choose it alongside Google Ads to build a cross-platform search advertising dashboard comparing performance on both search engines.
LinkedIn Ads targets B2B audiences by job title, company, and industry — choose it over Google Ads for B2B campaigns where professional targeting matters more than search intent keyword matching.
Frequently asked questions
Does Retool have a native Google Ads connector?
Retool has a native Google Analytics connector, but not a dedicated Google Ads connector. For Google Ads, you connect via a REST API Resource using Google Ads API OAuth 2.0 authentication with a developer token. The setup is more complex than most API integrations due to the developer token requirement and OAuth flow, but once configured you have full access to GAQL for campaign, keyword, and ad group reporting.
What is GAQL and why do I need to learn it for Google Ads in Retool?
GAQL (Google Ads Query Language) is Google's SQL-like query language for the Ads API. Unlike REST APIs that expose resources as endpoints, Google Ads API uses GAQL queries sent via POST to a single search endpoint. GAQL queries specify which resource to query (campaign, keyword_view, etc.), which fields to select, and how to filter and sort. Learning basic GAQL is necessary to fetch any Google Ads data — there are no pre-built action dropdowns like in native connectors.
Do I need a test developer token or basic access to query real Google Ads data?
You need basic access (or standard access) to the Google Ads API to query real campaign data. A test developer token — which you get immediately upon application — only works with test Google Ads accounts created specifically for API testing. To query your actual campaign performance data, apply for basic access in Google Ads → Tools & Settings → API Center. Approval typically takes 1–5 business days and requires describing your use case.
How do I query multiple Google Ads accounts from one Retool dashboard?
For manager account (MCC) access, add the login-customer-id header set to your MCC customer ID in the REST API Resource configuration. Then query individual leaf account IDs by dynamically changing the customer ID in the endpoint path: /v17/customers/{{ select_account.value }}/googleAds:search. Populate the account selector by calling GET /v17/customers:listAccessibleCustomers which returns all accounts your credentials can access.
What is the Google Ads API rate limit?
Google Ads API rate limits vary by developer token access level. Basic access allows up to 15,000 requests per day and 1,000 per minute. Standard access has higher limits. Rate limit errors return HTTP 429 with a Retry-After header. For Retool dashboards, use query caching (5–10 minutes) for performance reports that don't change frequently — this dramatically reduces API call volume while keeping the dashboard responsive.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation