How to Integrate Google Ads with Your Headless CMS
Connect structured campaign content to Google Ads so product launches, offers, landing pages, and ad copy can publish once and sync to ads without copy-paste work.
What is Google Ads?
Google Ads is Googleβs advertising platform for running search, display, shopping, video, app, and Performance Max campaigns across Google properties and partner inventory. Marketing teams, growth teams, agencies, and commerce companies use it to create campaigns, manage budgets, target audiences, and measure conversions. Its core capability is matching ads to intent, especially in Google Search, where campaign data, landing pages, keywords, assets, and bidding rules all need to stay accurate.
Why integrate Google Ads with a headless CMS?
Google Ads works best when campaign content matches the page, product, or offer a person lands on. That gets hard when your landing page copy lives in one place, your promo details live in a spreadsheet, and your ad headlines are typed directly into Google Ads. A price changes from $49 to $39, but the ad still says $49. A landing page gets unpublished, but the final URL is still active in a campaign. Those small gaps can waste budget fast.
Architecture overview
A typical flow starts when an editor publishes or updates a campaign document in Sanity Studio. A webhook listens for publish events, or a Sanity Function runs directly on the content mutation. The sync code receives the document ID, uses @sanity/client to query the Content Lake with GROQ, and returns only the fields needed by Google Ads, such as campaign name, ad group resource name, final URL, headlines, descriptions, labels, start date, end date, and status. The Function then calls the Google Ads API through an OAuth refresh token, developer token, customer ID, and optional manager account login customer ID. For example, it can create a responsive search ad inside an existing ad group, update ad assets, apply labels, or pause an ad when the Sanity document is archived. After Google serves the ad, the end user clicks from Google Search or another Google Ads surface to the landing page powered by the same structured content.
Common use cases
Search ad copy from approved campaign content
Sync headline and description variants from Sanity into Google Ads responsive search ads after legal, brand, and regional review.
Product promo ads tied to live product data
Use product references, prices, promo dates, and landing URLs from the Content Lake to keep Google Ads offers aligned with current product pages.
Localized ads for regional landing pages
Generate location-specific final URLs, headlines, and labels for hundreds of city or store pages without maintaining a spreadsheet.
Automatic pausing for expired offers
Pause or label ads when a Sanity campaign document reaches its end date, is unpublished, or changes approval status.
Step-by-step integration
- 1
Set up Google Ads API access
Create or choose a Google Ads account, request a developer token in the Google Ads API Center, create a Google Cloud OAuth client, and generate a refresh token for the Google Ads user that can edit the target customer account. If you use a manager account, capture the login customer ID too.
- 2
Install the SDK and Sanity client
In your sync service or Sanity Function project, install google-ads-api and @sanity/client. Store GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET, GOOGLE_ADS_REFRESH_TOKEN, GOOGLE_ADS_CUSTOMER_ID, and SANITY_API_TOKEN as environment variables.
- 3
Model campaign content in Sanity Studio
Create a campaign schema with fields such as title, finalUrl, adGroupResourceName, headlines, descriptions, approvalStatus, startDate, endDate, regions, product references, and googleAdsResourceName. Add validation for Google Ads limits, such as 30 characters for responsive search ad headlines and 90 characters for descriptions.
- 4
Create the sync trigger
Use a Sanity webhook filtered to published campaign documents, or use a Sanity Function triggered by content mutations. Pass the document ID to the sync handler so it can fetch the latest published content from the Content Lake.
- 5
Call the Google Ads API
Use GROQ to fetch the campaign document and referenced product or landing page data, then call Google Ads API mutate operations to create or update ads, assets, labels, or status. Keep the first version conservative, for example create paused ads that a marketer reviews in Google Ads before enabling.
- 6
Test with a safe campaign and verify the landing page
Run the integration against a test customer account or a low-budget campaign. Confirm character limits, final URLs, tracking templates, policy review status, and click paths from the ad to the page powered by Sanity.
Code example
import {createClient} from '@sanity/client';
import {GoogleAdsApi} from 'google-ads-api';
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: '2025-01-01',
token: process.env.SANITY_API_TOKEN!,
useCdn: false
});
const ads = new GoogleAdsApi({
client_id: process.env.GOOGLE_ADS_CLIENT_ID!,
client_secret: process.env.GOOGLE_ADS_CLIENT_SECRET!,
developer_token: process.env.GOOGLE_ADS_DEVELOPER_TOKEN!
});
export async function POST(req: Request) {
const {ids} = await req.json();
const id = ids?.created?.[0] || ids?.updated?.[0];
if (!id) return new Response('No document id', {status: 202});
const campaign = await sanity.fetch(`*[_id == $id][0]{
title,
finalUrl,
adGroupResourceName,
headlines[]{text},
descriptions[]{text}
}`, {id});
const customer = ads.Customer({
customer_id: process.env.GOOGLE_ADS_CUSTOMER_ID!,
login_customer_id: process.env.GOOGLE_ADS_LOGIN_CUSTOMER_ID,
refresh_token: process.env.GOOGLE_ADS_REFRESH_TOKEN!
});
await customer.mutateResources([{
entity: 'ad_group_ad',
operation: 'create',
resource: {
ad_group: campaign.adGroupResourceName,
status: 'PAUSED',
ad: {
final_urls: [campaign.finalUrl],
responsive_search_ad: {
headlines: campaign.headlines.slice(0, 15),
descriptions: campaign.descriptions.slice(0, 4)
}
}
}
}]);
return Response.json({synced: true, title: campaign.title});
}How Sanity + Google Ads works
Build your Google Ads integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect campaign content with Google Ads safely.
Start building free βCMS approaches to Google Ads
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Ad-ready campaign fields | Campaign copy often sits inside page fields or rich text, so a developer has to parse content before sending it to Google Ads. | Schema-as-code lets you model headlines, descriptions, final URLs, promo dates, regions, approval status, and product references as typed fields. |
| Real-time sync on publish | Teams often rely on manual exports, scheduled jobs, or plugin-specific sync behavior. | Webhooks or Functions can run server-side sync logic when content changes, with 500K Function invocations per month included. |
| Field-level control for Google Ads API payloads | APIs may return full pages, rendered HTML, or fields the ad sync doesn't need. | GROQ can filter, project, and join references in one query, so the Google Ads request gets only approved fields. |
| Editorial guardrails before spend changes | Approval workflows are often page-focused, not built around ad copy variants, policy notes, or campaign status. | Sanity Studio can validate Google Ads character limits, require approvalStatus before sync, and use Content Releases for launch timing. |
| Multi-channel campaign reuse | The web page is usually the primary output, and ad copy is maintained separately. | One structured back end can feed landing pages, mobile promos, Google Ads, lifecycle emails, and AI agents from the same campaign document. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Meta Ads
Use approved campaign content, product data, and landing URLs from Sanity to support paid social ads across Meta placements.
Sanity + HubSpot
Connect landing page content and campaign metadata with HubSpot forms, lists, and lifecycle workflows.
Sanity + Mailchimp
Reuse campaign copy, product promos, and audience-specific messaging from Sanity in email campaigns.