PPC Advertising10 min readAPI v22 - Oct 2025

Google Ads API AI Automation: Complete October 2025 Guide

Master Google Ads API v22 with AI-powered automation. Learn view-based conversions, AI Max reporting, and generative asset creation. Complete implementation guide with production-ready code examples for October 2025.

Digital Applied Team
October 11, 2025
10 min read
v22
Latest API
Oct 2025
Release Date
AI-Powered
Generative Assets
View Conv
New Tracking

Key Takeaways

AI-Powered Asset Generation:: Use generative AI to create text and image assets automatically via the new AssetGenerationService (beta)
View-Based Conversions:: Track engaged-view conversions for Display and Video campaigns with enhanced attribution
AI Max Reporting:: Access detailed performance data for AI Max for Search campaigns via ai_max_search_term_ad_combination_view
Performance Max Upgrades:: Image enhancement, extraction automation, and new feed_types field for better reporting
Targetless Bidding:: New App campaign bidding goals for rapid scaling without CPA/ROAS targets

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.

Major Features in v22

  • AssetGenerationService (Beta): Generate text and image assets using generative AI based on URLs, prompts, keywords, and campaign context
  • 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_view provides detailed performance data for AI Max for Search campaigns
  • Performance Max Enhancements: Image enhancement, extraction automation, and enhanced reporting with feed_types field
  • Targetless Bidding for App Campaigns: New OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA and OPTIMIZE_TOTAL_VALUE_WITHOUT_TARGET_ROAS goals
  • Smart Bidding Diversity Metrics: Target ROAS strategies on Search can retrieve time-segmented diversity metrics

These updates make Google Ads API v22 the most AI-focused release to date, enabling advertisers to automate asset creation, gain deeper insights into AI-driven campaigns, and optimize performance with enhanced bidding strategies.

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
  • • Impression share and quality metrics at the combination level

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_url,
            campaign.name,
            ad_group.name,
            metrics.impressions,
            metrics.clicks,
            metrics.conversions,
            metrics.cost_micros,
            metrics.average_cpc,
            metrics.conversion_rate,
            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_url,
                '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,
                'avg_cpc': row.metrics.average_cpc / 1_000_000,
                'conversion_rate': row.metrics.conversion_rate,
                '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:
    headline_performance[combo['headline']].append({
        'search_term': combo['search_term'],
        'conversions': combo['conversions'],
        'conversion_rate': combo['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 headlines and descriptions using AI"""
    asset_generation_service = client.get_service("AssetGenerationService")

    # Build request
    request = client.get_type("GenerateTextAssetsRequest")
    request.customer_id = customer_id

    # Input: Final URL (required)
    request.final_url = final_url

    # Optional: Add keywords for context
    if keywords:
        request.keywords.extend(keywords)

    # Optional: Add freeform prompt for customization
    if prompt:
        request.prompt = prompt

    # Optional: Use existing campaign context
    # request.campaign_id = "YOUR_CAMPAIGN_ID"

    # Configure generation parameters
    request.number_of_headlines = 10
    request.number_of_descriptions = 5
    request.headline_length_preference = "SHORT"  # SHORT, MEDIUM, or LONG

    # Generate assets
    response = asset_generation_service.generate_text_assets(request=request)

    # Process results
    generated_assets = {
        'headlines': [],
        'descriptions': []
    }

    for headline in response.headlines:
        generated_assets['headlines'].append({
            'text': headline.text,
            'length': len(headline.text),
            'confidence_score': headline.confidence_score
        })

    for description in response.descriptions:
        generated_assets['descriptions'].append({
            'text': description.text,
            'length': len(description.text),
            'confidence_score': description.confidence_score
        })

    return generated_assets

# 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:")
for headline in assets['headlines'][:5]:
    print(f"  {headline['text']} (confidence: {headline['confidence_score']:.2f})")

print("\nGenerated Descriptions:")
for desc in assets['descriptions'][:3]:
    print(f"  {desc['text']} (confidence: {desc['confidence_score']:.2f})")

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("GenerateImageAssetsRequest")
    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

    # Configure image parameters
    request.aspect_ratio = "SQUARE"  # SQUARE, LANDSCAPE, or PORTRAIT
    request.number_of_images = 5

    # Generate images
    response = asset_generation_service.generate_image_assets(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
  • • Monitor confidence scores
  • • 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.

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:

  • • feed_types field for asset source tracking
  • • New performance segments by asset group
  • • 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,
            asset_group.name,
            asset_group.id,
            asset_group_asset.feed_types,
            metrics.impressions,
            metrics.clicks,
            metrics.conversions,
            metrics.all_conversions,
            metrics.cost_micros,
            metrics.conversion_value,
            segments.asset_interaction_target.asset,
            segments.asset_interaction_target.interaction_on_this_asset,
            segments.date
        FROM asset_group_asset
        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.asset_group_asset.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 bidding goal
    if goal_type == "CONVERSIONS":
        # Optimize for in-app conversions without target CPA
        campaign.bidding_strategy_type = (
            client.enums.BiddingStrategyTypeEnum.OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA
        )
    elif goal_type == "VALUE":
        # Optimize for total value without target ROAS
        campaign.bidding_strategy_type = (
            client.enums.BiddingStrategyTypeEnum.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}")

Production-Ready Code Examples

Here are complete, production-ready examples integrating multiple v22 features for common automation scenarios:

Example: Automated Campaign Creator with AI Assets

# Python: Complete automation - create campaign with AI-generated 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_assets = self.generate_assets(
            final_url=product_data['url'],
            keywords=product_data['keywords']
        )

        # Step 2: Generate image assets
        print("Generating AI image assets...")
        image_assets = self.generate_images(
            final_url=product_data['url']
        )

        # Step 3: Create campaign
        print("Creating campaign...")
        campaign = self.create_campaign(
            name=product_data['name'],
            budget=product_data['budget']
        )

        # Step 4: 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 5: Create responsive search ad with AI assets
        print("Creating responsive search ad...")
        ad = self.create_responsive_ad(
            ad_group_id=ad_group.id,
            headlines=[h['text'] for h in text_assets['headlines'][:15]],
            descriptions=[d['text'] for d in text_assets['descriptions'][:4]],
            final_url=product_data['url']
        )

        # Step 6: 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("GenerateTextAssetsRequest")
        request.customer_id = self.customer_id
        request.final_url = final_url
        request.keywords.extend(keywords)
        request.number_of_headlines = 15
        request.number_of_descriptions = 4

        response = asset_gen_service.generate_text_assets(request=request)

        return {
            'headlines': [
                {'text': h.text, 'confidence': h.confidence_score}
                for h in response.headlines
            ],
            'descriptions': [
                {'text': d.text, 'confidence': d.confidence_score}
                for d in response.descriptions
            ]
        }

    def generate_images(self, final_url):
        """Generate image assets using AI"""
        asset_gen_service = self.client.get_service("AssetGenerationService")

        request = self.client.get_type("GenerateImageAssetsRequest")
        request.customer_id = self.customer_id
        request.final_url = final_url
        request.number_of_images = 5
        request.aspect_ratio = "SQUARE"

        response = asset_gen_service.generate_image_assets(request=request)

        return [
            {
                'url': img.url,
                'asset_id': img.asset_id,
                'dimensions': f"{img.width}x{img.height}"
            }
            for img in response.images
        ]

    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: 15,000 (Standard), 10,000 (Basic)
  • Batch size: Maximum 5,000 operations per request
  • Requests per second: Throttle to 10-20 RPS
  • 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; confidence scores don't guarantee brand alignment
  • 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 currently using an earlier version of the Google Ads API, here's how to migrate to v22 and take advantage of the new features:

Step 1: Update Client Libraries

Python:

pip install --upgrade google-ads==22.0.0

Node.js:

npm install google-ads-api@22.0.0

Step 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; API surface 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

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.

Essential Resources

Frequently Asked Questions

Frequently Asked Questions

Related Articles

Explore more PPC automation strategies and API integration guides