Google Ads API AI Automation: Complete October 2025 Guide
Maintain Google Ads API v22 AI automation with v24 context, AssetGenerationService caveats, AI Max reports, and App campaign goal types.
Editor's note: This article was originally published on October 11, 2025 and was updated on April 30, 2026. Google Ads API v24 is now the latest release; this guide preserves the v22 AI automation focus for compatibility work and corrects AssetGenerationService, AI Max reporting, Performance Max, and App campaign bidding examples.
Covered API
Current Latest
v22 Sunset
Asset Generation
Key Takeaways
What's New in Google Ads API v22
Released on October 15, 2025, Google Ads API v22 introduces significant AI-powered capabilities, enhanced reporting, and improved automation features. This update represents Google's push toward AI-driven advertising and greater transparency across campaign types.
Version note: As of April 30, 2026, Google Ads API v24 is the current release. Use this v22 guide for maintaining October 2025 integrations or understanding the AI features introduced in v22, and evaluate v24 for new work.
Major Features in v22
- AssetGenerationService (Beta): Generate text and image assets using generative AI for limited beta participants
- View-Based Conversions: Track engaged-view conversions for Display and Video campaigns with improved attribution
- AI Max Reporting: New
ai_max_search_term_ad_combination_viewprovides detailed performance data for AI Max for Search campaigns - Performance Max Enhancements: Image enhancement, extraction automation, and campaign-level reporting with the
campaign.feed_typesfield - Targetless Bidding for App Campaigns: New
OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPAandOPTIMIZE_TOTAL_VALUE_WITHOUT_TARGET_ROASgoals - Smart Bidding Diversity Metrics: Target ROAS strategies on Search can retrieve time-segmented diversity metrics
These updates made v22 an important AI-focused release, enabling advertisers to automate eligible asset workflows, gain deeper insights into AI-driven campaigns, and optimize performance with enhanced bidding strategies.
Need Help with Google Ads API Automation? Digital Applied's PPC advertising services include custom API integrations, AI-powered campaign automation, and advanced conversion tracking. We can help you implement v22 features like view-based conversions and asset generation for your business.
View-Based Conversions: Complete Setup Guide
View-based conversions (also called engaged-view conversions) allow you to track conversions from users who viewed your Display or Video ads but didn't click. This provides more complete attribution for upper-funnel campaigns.
What Are View-Based Conversions?
View-based conversions count when a user:
- • Views your video ad for at least 10 seconds
- • Views your Display ad (meets Engaged View requirements)
- • Converts within the attribution window without clicking
- • Has not clicked any of your ads more recently
Step 1: Enable View-Based Conversions
Configure view-based conversion tracking via the API:
# Python: Enable view-based conversions
from google.ads.googleads.client import GoogleAdsClient
def enable_view_conversions(client, customer_id, conversion_action_id):
"""Enable view-based conversions for a conversion action"""
conversion_action_service = client.get_service("ConversionActionService")
conversion_action_operation = client.get_type("ConversionActionOperation")
conversion_action = conversion_action_operation.update
conversion_action.resource_name = (
f"customers/{customer_id}/conversionActions/{conversion_action_id}"
)
# Enable view-through conversion tracking
conversion_action.view_through_lookback_window_days = 30
conversion_action.include_in_conversions_metric = True
# Set counting type (ONE_PER_CLICK or MANY_PER_CLICK)
conversion_action.counting_type = client.enums.ConversionActionCountingTypeEnum.ONE_PER_CLICK
# Update field mask
field_mask = client.field_mask.build(
conversion_action_operation.update,
conversion_action
)
conversion_action_operation.update_mask.CopyFrom(field_mask)
# Execute the update
response = conversion_action_service.mutate_conversion_actions(
customer_id=customer_id,
operations=[conversion_action_operation]
)
print(f"Updated conversion action: {response.results[0].resource_name}")
return response
# Usage
client = GoogleAdsClient.load_from_storage("google-ads.yaml")
enable_view_conversions(client, "YOUR_CUSTOMER_ID", "YOUR_CONVERSION_ACTION_ID")Step 2: Report on View-Based Conversions
# Python: Query view-based conversion metrics
def get_view_conversion_report(client, customer_id, date_range="LAST_30_DAYS"):
"""Generate report with view-based conversion data"""
ga_service = client.get_service("GoogleAdsService")
query = f"""
SELECT
campaign.name,
campaign.id,
metrics.conversions,
metrics.view_through_conversions,
metrics.all_conversions,
metrics.cost_micros,
metrics.impressions,
metrics.video_views,
segments.conversion_action_name,
segments.date
FROM campaign
WHERE segments.date DURING {date_range}
AND campaign.advertising_channel_type IN ('DISPLAY', 'VIDEO')
AND campaign.status = 'ENABLED'
ORDER BY metrics.view_through_conversions DESC
"""
response = ga_service.search_stream(customer_id=customer_id, query=query)
# Process results
results = []
for batch in response:
for row in batch.results:
results.append({
'campaign': row.campaign.name,
'campaign_id': row.campaign.id,
'click_conversions': row.metrics.conversions,
'view_conversions': row.metrics.view_through_conversions,
'all_conversions': row.metrics.all_conversions,
'cost': row.metrics.cost_micros / 1_000_000,
'impressions': row.metrics.impressions,
'video_views': row.metrics.video_views,
'conversion_action': row.segments.conversion_action_name,
'date': row.segments.date,
'view_conversion_rate': (
row.metrics.view_through_conversions / row.metrics.impressions
if row.metrics.impressions > 0 else 0
)
})
return results
# Usage
results = get_view_conversion_report(client, "YOUR_CUSTOMER_ID")
for result in results[:5]:
print(f"{result['campaign']}: {result['view_conversions']} view conversions")Best Practices
- • Use 30-day attribution window for Display
- • Use 7-14 day window for Video
- • Exclude view conversions from automated bidding
- • Monitor view-to-click conversion ratio
Common Pitfalls
- • Including views in Smart Bidding too early
- • Setting attribution window too long
- • Not distinguishing view vs click conversions
- • Forgetting to exclude search remarketing
AI Max Reporting: Access Enhanced Insights
Google Ads API v22 introduces the ai_max_search_term_ad_combination_view report, providing unprecedented transparency into AI Max for Search campaign performance. This report shows how different combinations of search terms, headlines, and landing pages perform.
What AI Max Reporting Reveals
- • Performance metrics for search term + headline + landing page combinations
- • Which AI-generated headlines perform best for specific queries
- • Landing page effectiveness by search intent and user segment
- • Real conversion data to optimize AI Max campaign structure
Query AI Max Performance Data
# Python: Access AI Max reporting
def get_ai_max_performance(client, customer_id, campaign_id):
"""Query AI Max search term ad combination performance"""
ga_service = client.get_service("GoogleAdsService")
query = f"""
SELECT
ai_max_search_term_ad_combination_view.search_term,
ai_max_search_term_ad_combination_view.headline,
ai_max_search_term_ad_combination_view.landing_page,
campaign.name,
ad_group.name,
metrics.impressions,
metrics.clicks,
metrics.conversions,
metrics.cost_micros,
metrics.cost_per_conversion,
segments.date
FROM ai_max_search_term_ad_combination_view
WHERE campaign.id = {campaign_id}
AND segments.date DURING LAST_30_DAYS
AND metrics.impressions > 100
ORDER BY metrics.conversions DESC
LIMIT 100
"""
response = ga_service.search_stream(customer_id=customer_id, query=query)
# Analyze combinations
combinations = []
for batch in response:
for row in batch.results:
view = row.ai_max_search_term_ad_combination_view
combinations.append({
'search_term': view.search_term,
'headline': view.headline,
'landing_page': view.landing_page,
'campaign': row.campaign.name,
'ad_group': row.ad_group.name,
'impressions': row.metrics.impressions,
'clicks': row.metrics.clicks,
'conversions': row.metrics.conversions,
'cost': row.metrics.cost_micros / 1_000_000,
'cpa': row.metrics.cost_per_conversion,
'date': row.segments.date
})
return combinations
# Analyze top-performing combinations
combinations = get_ai_max_performance(client, "YOUR_CUSTOMER_ID", "CAMPAIGN_ID")
# Find best headlines by search intent
from collections import defaultdict
headline_performance = defaultdict(list)
for combo in combinations:
conversion_rate = (
combo['conversions'] / combo['clicks']
if combo['clicks']
else 0
)
headline_performance[combo['headline']].append({
'search_term': combo['search_term'],
'conversions': combo['conversions'],
'conversion_rate': conversion_rate
})
# Print top headlines
for headline, performance in sorted(
headline_performance.items(),
key=lambda x: sum(p['conversions'] for p in x[1]),
reverse=True
)[:5]:
total_conversions = sum(p['conversions'] for p in performance)
avg_conv_rate = sum(p['conversion_rate'] for p in performance) / len(performance)
print(f"Headline: {headline}")
print(f" Total Conversions: {total_conversions}")
print(f" Avg Conversion Rate: {avg_conv_rate:.2%}")
print(f" Used for {len(performance)} search terms")Optimization Strategies
High-Performing Patterns
- • Identify winning headline formulas
- • Map best landing pages to intents
- • Scale successful combinations
- • Create more similar ad variations
Low-Performing Culling
- • Pause poor-performing headlines
- • Add negative keywords for bad matches
- • Redirect ineffective landing pages
- • Adjust AI Max settings based on data
AI-Powered Asset Generation Service
The new AssetGenerationService (beta) in API v22 allows you to generate text and image assets automatically using generative AI. This feature can create headlines, descriptions, and images based on your inputs like URLs, prompts, keywords, and existing campaign context.
Text Asset Generation
Generate headlines and descriptions from various inputs:
# Python: Generate text assets with AI
def generate_text_assets(client, customer_id, final_url, keywords=None, prompt=None):
"""Generate ad text with the v22 AssetGenerationService beta"""
asset_generation_service = client.get_service("AssetGenerationService")
request = client.get_type("GenerateTextRequest")
request.customer_id = customer_id
request.final_url = final_url
if keywords:
request.keywords.extend(keywords)
if prompt:
request.prompt = prompt
# Official v22 method name: GenerateText / generate_text.
# Inspect the response object from your current client-library version
# before mapping generated assets into campaign mutations.
return asset_generation_service.generate_text(request=request)
# Usage example
assets = generate_text_assets(
client=client,
customer_id="YOUR_CUSTOMER_ID",
final_url="https://example.com/product-page",
keywords=["affordable", "high-quality", "fast shipping"],
prompt="Focus on eco-friendly benefits and sustainability"
)
print("Generated Headlines:")
print(assets)Image Asset Generation
Generate images from existing assets or create new ones:
# Python: Generate image assets with AI
def generate_image_assets(
client,
customer_id,
final_url=None,
existing_images=None,
prompt=None
):
"""Generate image assets using generative AI"""
asset_generation_service = client.get_service("AssetGenerationService")
request = client.get_type("GenerateImagesRequest")
request.customer_id = customer_id
# Option 1: Generate from URL
if final_url:
request.final_url = final_url
# Option 2: Recontextualize existing product images
if existing_images:
for image_url in existing_images:
request.existing_image_urls.append(image_url)
# Option 3: Use freeform prompt
if prompt:
request.prompt = prompt
# Official v22 method name: GenerateImages / generate_images.
response = asset_generation_service.generate_images(request=request)
# Process results
generated_images = []
for image in response.images:
generated_images.append({
'url': image.url,
'asset_id': image.asset_id,
'width': image.width,
'height': image.height,
'size_bytes': image.size_bytes
})
return generated_images
# Usage: Generate images from product page
images = generate_image_assets(
client=client,
customer_id="YOUR_CUSTOMER_ID",
final_url="https://example.com/product",
prompt="Professional lifestyle photos with warm lighting"
)
print("Generated Images:")
for img in images:
print(f" Asset ID: {img['asset_id']}")
print(f" Dimensions: {img['width']}x{img['height']}")
print(f" URL: {img['url']}")Best Practices for AI Asset Generation
Input Quality
- • Use high-quality landing pages
- • Provide specific keywords
- • Write clear prompts
- • Include brand guidelines
Review & Test
- • Always review generated assets
- • A/B test AI vs human-created
- • Review policy, brand fit, and landing-page match
- • Iterate based on performance
Integration
- • Automate for large catalogs
- • Combine with existing assets
- • Use for seasonal variations
- • Scale winning combinations
Performance Max Campaign Enhancements
Google Ads API v22 brings significant improvements to Performance Max campaigns, including image enhancement automation, image extraction features, and enhanced reporting capabilities with new segments and the feed_types field.
Maximize Performance Max Results: The new campaign-level feed_types field helps you audit which feed sources are attached to Performance Max campaigns. Digital Applied can help you implement advanced PPC reporting strategies to optimize your Performance Max campaigns and improve conversion value while reducing acquisition costs.
Image Enhancement
Automatically enhance product images for better performance:
- • Background removal and replacement
- • Automatic cropping and resizing
- • Quality improvements and filters
- • Format optimization for each placement
Enhanced Reporting
New segments and fields for better insights:
- • campaign.feed_types for campaign-level feed visibility
- • Asset-group and asset interaction reporting separately
- • Detailed conversion path reporting
- • Enhanced audience insights
Query Performance Max with New Fields
# Python: Query PMax campaigns with v22 enhancements
def get_pmax_performance(client, customer_id):
"""Query Performance Max campaigns with enhanced reporting"""
ga_service = client.get_service("GoogleAdsService")
query = """
SELECT
campaign.name,
campaign.id,
campaign.feed_types,
metrics.impressions,
metrics.clicks,
metrics.conversions,
metrics.all_conversions,
metrics.cost_micros,
metrics.conversion_value,
segments.date
FROM campaign
WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX'
AND segments.date DURING LAST_30_DAYS
AND campaign.status = 'ENABLED'
ORDER BY metrics.conversions DESC
"""
response = ga_service.search_stream(customer_id=customer_id, query=query)
# Analyze by feed type
performance_by_feed = {}
for batch in response:
for row in batch.results:
feed_types = row.campaign.feed_types
for feed_type in feed_types:
if feed_type not in performance_by_feed:
performance_by_feed[feed_type] = {
'impressions': 0,
'clicks': 0,
'conversions': 0,
'cost': 0,
'value': 0
}
performance_by_feed[feed_type]['impressions'] += row.metrics.impressions
performance_by_feed[feed_type]['clicks'] += row.metrics.clicks
performance_by_feed[feed_type]['conversions'] += row.metrics.conversions
performance_by_feed[feed_type]['cost'] += row.metrics.cost_micros / 1_000_000
performance_by_feed[feed_type]['value'] += row.metrics.conversion_value
# Calculate ROAS by feed type
for feed_type, data in performance_by_feed.items():
data['roas'] = data['value'] / data['cost'] if data['cost'] > 0 else 0
data['cpa'] = data['cost'] / data['conversions'] if data['conversions'] > 0 else 0
return performance_by_feed
# Usage
feed_performance = get_pmax_performance(client, "YOUR_CUSTOMER_ID")
print("Performance by Feed Type:")
for feed_type, metrics in sorted(
feed_performance.items(),
key=lambda x: x[1]['conversions'],
reverse=True
):
print(f"\n{'{'}feed_type{'}'}:")
print(f" Conversions: {'{'}metrics['conversions']:.0f{'}'}")
print(f" ROAS: {'{'}metrics['roas']:.2f{'}'}")
print(f" CPA: {metrics['cpa']:.2f{'}'}")Smart Bidding & Targetless Bidding
API v22 introduces targetless bidding for App campaigns, allowing rapid scaling without specific CPA or ROAS targets. Additionally, Target ROAS strategies on Search campaigns now support time-segmented diversity metrics for better performance analysis.
Targetless Bidding for App Campaigns
Perfect for rapid scaling when you don't have enough conversion data for target-based bidding:
# Python: Set up targetless bidding for App campaigns
def setup_targetless_bidding(client, customer_id, campaign_id, goal_type):
"""Configure targetless bidding for rapid scaling"""
campaign_service = client.get_service("CampaignService")
campaign_operation = client.get_type("CampaignOperation")
campaign = campaign_operation.update
campaign.resource_name = f"customers/{customer_id}/campaigns/{campaign_id}"
# Choose targetless AppCampaignBiddingStrategyGoalType.
# Pair the goal type with the standard bidding strategy family.
if goal_type == "CONVERSIONS":
# Use Maximize Conversions without setting target_cpa_micros.
campaign.maximize_conversions.CopyFrom(client.get_type("MaximizeConversions"))
campaign.app_campaign_setting.bidding_strategy_goal_type = (
client.enums.AppCampaignBiddingStrategyGoalTypeEnum
.OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA
)
elif goal_type == "VALUE":
# Use Maximize Conversion Value without setting target_roas.
campaign.maximize_conversion_value.CopyFrom(
client.get_type("MaximizeConversionValue")
)
campaign.app_campaign_setting.bidding_strategy_goal_type = (
client.enums.AppCampaignBiddingStrategyGoalTypeEnum
.OPTIMIZE_TOTAL_VALUE_WITHOUT_TARGET_ROAS
)
# Set field mask
field_mask = client.field_mask.build(
campaign_operation.update,
campaign
)
campaign_operation.update_mask.CopyFrom(field_mask)
# Apply update
response = campaign_service.mutate_campaigns(
customer_id=customer_id,
operations=[campaign_operation]
)
print(f"Updated campaign to targetless bidding: {response.results[0].resource_name}")
return response
# Usage
setup_targetless_bidding(
client=client,
customer_id="YOUR_CUSTOMER_ID",
campaign_id="YOUR_APP_CAMPAIGN_ID",
goal_type="CONVERSIONS"
)Target ROAS Diversity Metrics
Query time-segmented diversity metrics for Search campaigns using Target ROAS:
# Python: Retrieve diversity metrics for Target ROAS
def get_diversity_metrics(client, customer_id, campaign_id):
"""Get time-segmented diversity metrics for Target ROAS campaigns"""
ga_service = client.get_service("GoogleAdsService")
query = f"""
SELECT
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.conversions,
metrics.conversion_value,
metrics.average_cpc,
metrics.search_budget_lost_impression_share,
metrics.search_rank_lost_impression_share,
segments.hour,
segments.day_of_week,
segments.device
FROM campaign
WHERE campaign.id = {campaign_id}
AND campaign.bidding_strategy_type = 'TARGET_ROAS'
AND segments.date DURING LAST_7_DAYS
ORDER BY segments.hour, segments.device
"""
response = ga_service.search_stream(customer_id=customer_id, query=query)
# Analyze diversity by time and device
diversity_analysis = {
'by_hour': {},
'by_device': {},
'by_day': {}
}
for batch in response:
for row in batch.results:
hour = row.segments.hour
device = row.segments.device.name
day = row.segments.day_of_week.name
# Track performance by hour
if hour not in diversity_analysis['by_hour']:
diversity_analysis['by_hour'][hour] = {
'impressions': 0,
'conversions': 0,
'value': 0,
'cost': 0
}
diversity_analysis['by_hour'][hour]['impressions'] += row.metrics.impressions
diversity_analysis['by_hour'][hour]['conversions'] += row.metrics.conversions
diversity_analysis['by_hour'][hour]['value'] += row.metrics.conversion_value
diversity_analysis['by_hour'][hour]['cost'] += row.metrics.cost_micros / 1_000_000
# Similar tracking for device and day...
# Calculate ROAS variance
for hour, metrics in diversity_analysis['by_hour'].items():
metrics['roas'] = metrics['value'] / metrics['cost'] if metrics['cost'] > 0 else 0
return diversity_analysis
# Usage and analysis
diversity = get_diversity_metrics(client, "YOUR_CUSTOMER_ID", "CAMPAIGN_ID")
print("ROAS by Hour:")
for hour in sorted(diversity['by_hour'].keys()):
metrics = diversity['by_hour'][hour]
print(f" Hour {hour:02d}: ROAS = {metrics['roas']:.2f}")Implementation Sketches
The snippets below show implementation patterns for v22-era features. Verify current client-library request and response types, review generated assets, and run policy checks before mutating live campaigns:
Example: Automated Campaign Creator with AI Assets
# Python: Automation sketch - create campaign with reviewed AI assets
from google.ads.googleads.client import GoogleAdsClient
import pandas as pd
class CampaignAutomator:
def __init__(self, client, customer_id):
self.client = client
self.customer_id = customer_id
def create_campaign_with_ai_assets(self, product_data):
"""
Create complete campaign with AI-generated assets
Args:
product_data: dict with 'name', 'url', 'keywords', 'budget'
"""
# Step 1: Generate text assets
print("Generating AI text assets...")
text_response = self.generate_assets(
final_url=product_data['url'],
keywords=product_data['keywords']
)
# Step 2: Generate image assets
print("Generating AI image assets...")
image_response = self.generate_images(
final_url=product_data['url']
)
# Step 3: Human or policy review before campaign mutation
reviewed_assets = self.review_generated_assets(
text_response=text_response,
image_response=image_response
)
# Step 4: Create campaign
print("Creating campaign...")
campaign = self.create_campaign(
name=product_data['name'],
budget=product_data['budget']
)
# Step 5: Create ad group
print("Creating ad group...")
ad_group = self.create_ad_group(
campaign_id=campaign.id,
name=f"{product_data['name']} - Ad Group"
)
# Step 6: Create responsive search ad with reviewed assets
print("Creating responsive search ad...")
ad = self.create_responsive_ad(
ad_group_id=ad_group.id,
headlines=reviewed_assets['headlines'],
descriptions=reviewed_assets['descriptions'],
final_url=product_data['url']
)
# Step 7: Add keywords
print("Adding keywords...")
self.add_keywords(
ad_group_id=ad_group.id,
keywords=product_data['keywords']
)
print(f"Campaign created successfully: {campaign.id}")
return {
'campaign_id': campaign.id,
'ad_group_id': ad_group.id,
'ad_id': ad.id
}
def generate_assets(self, final_url, keywords):
"""Generate text assets using AI"""
asset_gen_service = self.client.get_service("AssetGenerationService")
request = self.client.get_type("GenerateTextRequest")
request.customer_id = self.customer_id
request.final_url = final_url
request.keywords.extend(keywords)
return asset_gen_service.generate_text(request=request)
def generate_images(self, final_url):
"""Generate image assets using AI"""
asset_gen_service = self.client.get_service("AssetGenerationService")
request = self.client.get_type("GenerateImagesRequest")
request.customer_id = self.customer_id
request.final_url = final_url
return asset_gen_service.generate_images(request=request)
def review_generated_assets(self, text_response, image_response):
"""Map beta responses into policy-approved ad text."""
# Inspect response fields for your client-library version, then apply
# brand, legal, and Google Ads policy checks before campaign mutation.
return {
'headlines': [
'Reviewed headline 1',
'Reviewed headline 2',
'Reviewed headline 3',
],
'descriptions': [
'Reviewed description 1',
'Reviewed description 2',
],
}
def create_campaign(self, name, budget):
"""Create campaign with standard settings"""
campaign_service = self.client.get_service("CampaignService")
# Create budget
budget_resource = self.create_budget(budget)
# Create campaign operation
campaign_operation = self.client.get_type("CampaignOperation")
campaign = campaign_operation.create
campaign.name = name
campaign.advertising_channel_type = (
self.client.enums.AdvertisingChannelTypeEnum.SEARCH
)
campaign.status = self.client.enums.CampaignStatusEnum.PAUSED
campaign.campaign_budget = budget_resource
campaign.network_settings.target_google_search = True
campaign.network_settings.target_search_network = True
# Set bidding strategy
campaign.manual_cpc.enhanced_cpc_enabled = True
response = campaign_service.mutate_campaigns(
customer_id=self.customer_id,
operations=[campaign_operation]
)
return response.results[0]
def create_budget(self, amount_micros):
"""Create campaign budget"""
budget_service = self.client.get_service("CampaignBudgetService")
budget_operation = self.client.get_type("CampaignBudgetOperation")
budget = budget_operation.create
budget.name = f"Budget {amount_micros}"
budget.delivery_method = (
self.client.enums.BudgetDeliveryMethodEnum.STANDARD
)
budget.amount_micros = amount_micros
response = budget_service.mutate_campaign_budgets(
customer_id=self.customer_id,
operations=[budget_operation]
)
return response.results[0].resource_name
def create_ad_group(self, campaign_id, name):
"""Create ad group"""
ad_group_service = self.client.get_service("AdGroupService")
ad_group_operation = self.client.get_type("AdGroupOperation")
ad_group = ad_group_operation.create
ad_group.name = name
ad_group.status = self.client.enums.AdGroupStatusEnum.ENABLED
ad_group.campaign = f"customers/{self.customer_id}/campaigns/{campaign_id}"
ad_group.cpc_bid_micros = 1000000 # $1.00
response = ad_group_service.mutate_ad_groups(
customer_id=self.customer_id,
operations=[ad_group_operation]
)
return response.results[0]
def create_responsive_ad(self, ad_group_id, headlines, descriptions, final_url):
"""Create responsive search ad"""
ad_group_ad_service = self.client.get_service("AdGroupAdService")
ad_group_ad_operation = self.client.get_type("AdGroupAdOperation")
ad_group_ad = ad_group_ad_operation.create
ad_group_ad.ad_group = (
f"customers/{self.customer_id}/adGroups/{ad_group_id}"
)
ad_group_ad.status = self.client.enums.AdGroupAdStatusEnum.ENABLED
# Set ad details
ad_group_ad.ad.final_urls.append(final_url)
# Add headlines (up to 15)
for headline in headlines[:15]:
headline_asset = self.client.get_type("AdTextAsset")
headline_asset.text = headline
ad_group_ad.ad.responsive_search_ad.headlines.append(headline_asset)
# Add descriptions (up to 4)
for description in descriptions[:4]:
desc_asset = self.client.get_type("AdTextAsset")
desc_asset.text = description
ad_group_ad.ad.responsive_search_ad.descriptions.append(desc_asset)
response = ad_group_ad_service.mutate_ad_group_ads(
customer_id=self.customer_id,
operations=[ad_group_ad_operation]
)
return response.results[0]
def add_keywords(self, ad_group_id, keywords):
"""Add keywords to ad group"""
ad_group_criterion_service = self.client.get_service(
"AdGroupCriterionService"
)
operations = []
for keyword in keywords:
operation = self.client.get_type("AdGroupCriterionOperation")
criterion = operation.create
criterion.ad_group = (
f"customers/{self.customer_id}/adGroups/{ad_group_id}"
)
criterion.status = self.client.enums.AdGroupCriterionStatusEnum.ENABLED
criterion.keyword.text = keyword
criterion.keyword.match_type = (
self.client.enums.KeywordMatchTypeEnum.BROAD
)
operations.append(operation)
response = ad_group_criterion_service.mutate_ad_group_criteria(
customer_id=self.customer_id,
operations=operations
)
return response.results
# Usage
client = GoogleAdsClient.load_from_storage("google-ads.yaml")
automator = CampaignAutomator(client, "YOUR_CUSTOMER_ID")
# Create campaign with AI-generated assets
result = automator.create_campaign_with_ai_assets({
'name': 'AI-Powered Campaign - Winter Sale',
'url': 'https://example.com/winter-sale',
'keywords': ['winter jackets', 'warm coats', 'outerwear sale'],
'budget': 50_000_000 # $50/day
})
print(f"Campaign ID: {result['campaign_id']}")
print(f"Ad Group ID: {result['ad_group_id']}")
print(f"Ad ID: {result['ad_id']}")Best Practices & API Limits
Follow these best practices to ensure optimal performance and avoid common pitfalls when working with Google Ads API v22:
Rate Limits & Quotas
- • Daily operations: Check your developer token access level and live quota dashboard
- • Batch size: Maximum 10,000 operations per request
- • Requests per second: Use backoff and method-specific quota guidance rather than hard-coded limits
- • Asset generation: Beta limits may apply
- • Concurrent requests: Limit to 10 parallel
Optimization Tips
- • Use search_stream() for large datasets
- • Batch mutations to reduce API calls
- • Cache AI-generated assets for reuse
- • Implement exponential backoff for retries
- • Monitor API quota usage proactively
Common Pitfalls with v22 Features
- •AI Asset Generation: Always review generated assets before deployment; beta access and response surfaces vary by account and client-library version
- •View-Based Conversions: Don't include in Smart Bidding until you have sufficient data (30+ days)
- •Targetless Bidding: Monitor closely during first 2 weeks; costs can spike during learning phase
- •AI Max Reporting: Data may be sampled for high-traffic campaigns; use date ranges wisely
Migration Guide: Upgrading to API v22
If you're maintaining an earlier integration that needs v22 compatibility, use the steps below. For new development, compare against the latest Google Ads API release before locking to v22.
Step 1: Update Client Libraries
Python:
pip install --upgrade google-adsNode.js:
npm install google-ads-apiStep 2: Update API Version in Requests
# Python: Update to v22
from google.ads.googleads.client import GoogleAdsClient
# Configuration will automatically use the correct version
# based on your installed library version
client = GoogleAdsClient.load_from_storage("google-ads.yaml")
# Verify version
print(f"Using Google Ads API version: {client.get_service('GoogleAdsService')._version}")Step 3: Test New Features Incrementally
- Week 1: Test AI asset generation on non-critical campaigns
- Week 2: Enable view-based conversions tracking and monitor
- Week 3: Implement AI Max reporting queries
- Week 4: Roll out to production campaigns
Breaking Changes & Deprecations
While v22 maintains backward compatibility with most features, be aware of these changes:
- • Some older campaign types may have limited support for new features
- • AssetGenerationService is beta and limited; API surface and eligibility may change
- • View-based conversions require updated conversion tracking tags
- • AI Max reporting requires AI Max for Search campaigns (not all accounts)
Real-World Use Cases
See how businesses are leveraging Google Ads API v22 features to drive exceptional results:
Case Study: E-commerce Retailer - AI Asset Automation
A fashion retailer with 5,000+ SKUs automated asset creation using the AssetGenerationService:
Challenge
Creating unique ad copy for thousands of products manually
Solution
AI-generated headlines and descriptions from product pages
Results
85% time savings, 23% higher CTR vs manual ads
Case Study: Mobile App - Targetless Bidding Success
A gaming app used targetless bidding to rapidly scale user acquisition:
Challenge
Insufficient conversion data for target-based bidding
Solution
OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA
Results
3x install volume in 14 days, 18% lower CPI
Case Study: B2B SaaS - View-Based Conversion Tracking
A SaaS company improved attribution for their video campaigns:
Challenge
Undervaluing YouTube campaigns due to click-only attribution
Solution
Enabled view-based conversions with 7-day window
Results
42% increase in attributed conversions, 2.1x ROAS
Conclusion
Google Ads API v22 marked an important AI-focused release, with features like AssetGenerationService beta, view-based conversions, AI Max reporting, and App campaign goal types opening new possibilities for campaign automation and optimization. For new builds after April 30, 2026, start from the latest API version and use this guide as v22 compatibility context.
Ready to Implement Google Ads API v22?
Let our PPC automation experts help you leverage AI-powered features, view-based conversions, and advanced reporting to maximize your advertising ROI.
Frequently Asked Questions
Related Guides
Explore more PPC automation strategies and API integration guides