CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-google-ads

Client library for the Google Ads API providing comprehensive access to advertising management, reporting, and analytics capabilities.

Pending
Overview
Eval results
Files

reporting-search.mddocs/

Reporting and Search

Comprehensive reporting capabilities using the Google Ads Query Language (GAQL) for data retrieval, performance analysis, and custom reporting. The GoogleAdsService provides the primary interface for querying Google Ads data with flexible search and streaming options.

Capabilities

Search Operations

The GoogleAdsService provides powerful search functionality using GAQL (Google Ads Query Language) for retrieving campaign, ad group, keyword, and performance data.

class GoogleAdsService:
    """Main service for searching and reporting Google Ads data."""
    
    def search(
        self,
        customer_id: str,
        query: str,
        page_size: int = None,
        return_total_results_count: bool = False,
        summary_row_setting: str = None
    ) -> SearchGoogleAdsResponse:
        """
        Search for Google Ads data using GAQL.
        
        Parameters:
        - customer_id: Customer ID to search within
        - query: GAQL query string
        - page_size: Number of results per page (max 10,000)
        - return_total_results_count: Include total results count
        - summary_row_setting: Include summary row (NO_SUMMARY_ROW, SUMMARY_ROW_WITH_RESULTS, SUMMARY_ROW_ONLY)
        
        Returns:
        SearchGoogleAdsResponse with query results
        
        Raises:
        - GoogleAdsException: If query is invalid or access denied
        """
    
    def search_stream(
        self,
        customer_id: str,
        query: str,
        summary_row_setting: str = None
    ) -> Iterator[SearchGoogleAdsStreamResponse]:
        """
        Stream search results for large data sets.
        
        Parameters:
        - customer_id: Customer ID to search within
        - query: GAQL query string
        - summary_row_setting: Include summary row setting
        
        Returns:
        Iterator of SearchGoogleAdsStreamResponse objects
        
        Raises:
        - GoogleAdsException: If query is invalid or access denied
        """

Mutate Operations

Bulk mutation operations for creating, updating, and deleting multiple resources in a single request.

def mutate(
    self,
    customer_id: str,
    mutate_operations: list,
    partial_failure: bool = False,
    validate_only: bool = False,
    response_content_type: str = None
) -> MutateGoogleAdsResponse:
    """
    Perform multiple mutations in a single request.
    
    Parameters:
    - customer_id: Customer ID for mutations
    - mutate_operations: List of MutateOperation objects
    - partial_failure: Continue on individual operation failures
    - validate_only: Validate operations without executing
    - response_content_type: Response content type (MUTABLE_RESOURCE, RESOURCE_NAME_ONLY)
    
    Returns:
    MutateGoogleAdsResponse with operation results
    
    Raises:
    - GoogleAdsException: If operations fail
    """

Google Ads Field Service

Metadata service for discovering available fields, their types, and relationships for GAQL queries.

class GoogleAdsFieldService:
    """Service for Google Ads field metadata."""
    
    def get_google_ads_field(
        self,
        resource_name: str
    ) -> GoogleAdsField:
        """
        Get metadata for a specific Google Ads field.
        
        Parameters:
        - resource_name: Resource name of the field
        
        Returns:
        GoogleAdsField with field metadata
        """
    
    def search_google_ads_fields(
        self,
        query: str,
        page_size: int = None
    ) -> SearchGoogleAdsFieldsResponse:
        """
        Search for Google Ads fields using query.
        
        Parameters:
        - query: Search query for fields
        - page_size: Number of results per page
        
        Returns:
        SearchGoogleAdsFieldsResponse with field results
        """

Usage Examples

Basic Search Query

from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException

client = GoogleAdsClient.load_from_storage("google-ads.yaml")
googleads_service = client.get_service("GoogleAdsService")

# Basic campaign performance query
query = """
    SELECT 
        campaign.id,
        campaign.name,
        campaign.status,
        campaign.advertising_channel_type,
        metrics.impressions,
        metrics.clicks,
        metrics.cost_micros,
        metrics.ctr,
        metrics.average_cpc
    FROM campaign
    WHERE campaign.status = 'ENABLED'
        AND segments.date DURING LAST_30_DAYS
    ORDER BY metrics.clicks DESC
    LIMIT 50
"""

try:
    response = googleads_service.search(
        customer_id="1234567890",
        query=query,
        page_size=50
    )
    
    for row in response:
        campaign = row.campaign
        metrics = row.metrics
        
        print(f"Campaign: {campaign.name} (ID: {campaign.id})")
        print(f"Status: {campaign.status.name}")
        print(f"Type: {campaign.advertising_channel_type.name}")
        print(f"Impressions: {metrics.impressions}")
        print(f"Clicks: {metrics.clicks}")
        print(f"Cost: ${metrics.cost_micros / 1_000_000:.2f}")
        print(f"CTR: {metrics.ctr:.2%}")
        print("---")
        
except GoogleAdsException as ex:
    print(f"Request failed: {ex.error.code().name}")
    for error in ex.error.details:
        print(f"Error: {error.message}")

Streaming Large Results

# Stream large data sets efficiently
query = """
    SELECT 
        keyword_view.resource_name,
        ad_group.id,
        ad_group.name,
        ad_group_criterion.keyword.text,
        ad_group_criterion.keyword.match_type,
        metrics.impressions,
        metrics.clicks,
        metrics.cost_micros
    FROM keyword_view
    WHERE segments.date DURING LAST_7_DAYS
        AND metrics.impressions > 0
"""

try:
    stream = googleads_service.search_stream(
        customer_id="1234567890",
        query=query
    )
    
    keyword_count = 0
    for batch in stream:
        for row in batch.results:
            keyword = row.ad_group_criterion.keyword
            metrics = row.metrics
            
            print(f"Keyword: {keyword.text}")
            print(f"Match Type: {keyword.match_type.name}")
            print(f"Impressions: {metrics.impressions}")
            print(f"Clicks: {metrics.clicks}")
            
            keyword_count += 1
            
    print(f"Total keywords processed: {keyword_count}")
    
except GoogleAdsException as ex:
    print(f"Stream failed: {ex.error.code().name}")

Advanced Segmentation Query

# Multi-dimensional reporting with segments
query = """
    SELECT 
        campaign.id,
        campaign.name,
        ad_group.id,
        ad_group.name,
        segments.device,
        segments.date,
        segments.hour,
        metrics.impressions,
        metrics.clicks,
        metrics.conversions,
        metrics.cost_micros
    FROM ad_group
    WHERE campaign.advertising_channel_type = 'SEARCH'
        AND segments.date DURING LAST_14_DAYS
        AND metrics.impressions > 100
    ORDER BY segments.date DESC, metrics.clicks DESC
"""

response = googleads_service.search(
    customer_id="1234567890",
    query=query,
    return_total_results_count=True
)

print(f"Total results: {response.total_results_count}")

for row in response:
    segments = row.segments
    metrics = row.metrics
    
    print(f"Date: {segments.date}")
    print(f"Hour: {segments.hour}")
    print(f"Device: {segments.device.name}")
    print(f"Campaign: {row.campaign.name}")
    print(f"Ad Group: {row.ad_group.name}")
    print(f"Performance: {metrics.clicks} clicks, {metrics.conversions} conversions")
    print("---")

Field Discovery

# Discover available fields for reporting
field_service = client.get_service("GoogleAdsFieldService")

# Search for campaign-related fields
field_query = """
    SELECT 
        name,
        category,
        data_type,
        selectable,
        filterable,
        sortable
    FROM google_ads_field
    WHERE name LIKE 'campaign.%'
        AND selectable = true
    ORDER BY name
"""

field_response = field_service.search_google_ads_fields(
    query=field_query,
    page_size=100
)

print("Available campaign fields:")
for field in field_response.results:
    print(f"- {field.name} ({field.data_type.name})")
    if field.filterable:
        print("  [Filterable]")
    if field.sortable:
        print("  [Sortable]")

Custom Date Range Reporting

# Reporting with custom date ranges and comparisons
query = """
    SELECT 
        campaign.id,
        campaign.name,
        segments.date,
        metrics.impressions,
        metrics.clicks,
        metrics.cost_micros,
        metrics.conversions,
        metrics.conversions_value
    FROM campaign
    WHERE segments.date BETWEEN '2024-01-01' AND '2024-01-31'
        AND campaign.status IN ('ENABLED', 'PAUSED')
    ORDER BY segments.date, campaign.name
"""

response = googleads_service.search(
    customer_id="1234567890",
    query=query,
    summary_row_setting=client.enums.SummaryRowSettingEnum.SUMMARY_ROW_WITH_RESULTS
)

# Process regular results
campaign_data = {}
for row in response:
    if hasattr(row, 'campaign'):  # Regular row
        campaign_id = row.campaign.id
        date = row.segments.date
        
        if campaign_id not in campaign_data:
            campaign_data[campaign_id] = {
                'name': row.campaign.name,
                'daily_data': {}
            }
        
        campaign_data[campaign_id]['daily_data'][date] = {
            'impressions': row.metrics.impressions,
            'clicks': row.metrics.clicks,
            'cost': row.metrics.cost_micros / 1_000_000,
            'conversions': row.metrics.conversions
        }

# Process summary row
if hasattr(response, 'summary_row') and response.summary_row:
    summary = response.summary_row.metrics
    print(f"Total Summary:")
    print(f"Impressions: {summary.impressions}")
    print(f"Clicks: {summary.clicks}")
    print(f"Cost: ${summary.cost_micros / 1_000_000:.2f}")
    print(f"Conversions: {summary.conversions}")

Response Types

class SearchGoogleAdsResponse:
    """Response from search operations."""
    results: list  # List of GoogleAdsRow objects
    next_page_token: str  # Token for pagination
    total_results_count: int  # Total number of results
    field_mask: object  # Field mask for the query
    summary_row: GoogleAdsRow  # Summary row if requested

class GoogleAdsRow:
    """Individual result row from search."""
    # Available attributes depend on SELECT fields in query
    campaign: object  # Campaign data if selected
    ad_group: object  # Ad group data if selected
    ad_group_ad: object  # Ad group ad data if selected
    metrics: object  # Metrics data if selected
    segments: object  # Segments data if selected
    # ... many other resource types

class GoogleAdsField:
    """Metadata for a Google Ads field."""
    name: str  # Field name
    category: str  # Field category
    data_type: str  # Data type (STRING, INT64, DOUBLE, etc.)
    selectable: bool  # Can be used in SELECT
    filterable: bool  # Can be used in WHERE
    sortable: bool  # Can be used in ORDER BY
    attribute_resources: list  # Related resources

Query Language (GAQL)

# GAQL syntax examples
GAQL_PATTERNS = {
    'basic_select': "SELECT field1, field2 FROM resource",
    'with_where': "SELECT * FROM campaign WHERE campaign.status = 'ENABLED'",
    'with_segments': "SELECT campaign.name, segments.date, metrics.clicks FROM campaign",
    'with_order': "SELECT * FROM campaign ORDER BY metrics.clicks DESC",
    'with_limit': "SELECT * FROM campaign LIMIT 100",
    'date_range': "WHERE segments.date DURING LAST_30_DAYS",
    'custom_date': "WHERE segments.date BETWEEN '2024-01-01' AND '2024-01-31'",
    'multiple_conditions': "WHERE campaign.status = 'ENABLED' AND metrics.clicks > 100",
    'in_operator': "WHERE campaign.status IN ('ENABLED', 'PAUSED')",
    'like_operator': "WHERE campaign.name LIKE '%brand%'"
}

Constants

# Summary row settings
SUMMARY_ROW_SETTINGS = {
    'NO_SUMMARY_ROW': 'Do not include summary row',
    'SUMMARY_ROW_WITH_RESULTS': 'Include summary row with results',
    'SUMMARY_ROW_ONLY': 'Return only summary row'
}

# Response content types
RESPONSE_CONTENT_TYPES = {
    'RESOURCE_NAME_ONLY': 'Return only resource names',
    'MUTABLE_RESOURCE': 'Return full mutable resource data'
}

# Maximum page size
MAX_PAGE_SIZE = 10000

Install with Tessl CLI

npx tessl i tessl/pypi-google-ads

docs

ad-management.md

asset-management.md

audience-management.md

batch-operations.md

campaign-management.md

client-setup.md

conversion-tracking.md

index.md

reporting-search.md

targeting-keywords.md

tile.json