Skip to content

Google Ads

Overview

The Google Ads task integrates BaseCloud CRM with Google Ads API v19, enabling automated campaign analytics, offline conversion tracking, and custom reporting using GAQL (Google Ads Query Language).

Key Features:

  • 3 Actions: Get metrics, upload offline conversions, custom GAQL queries
  • OAuth 2.0 Authentication: Secure Google integration with automatic token refresh
  • GAQL Support: SQL-like query language for advanced reporting
  • Offline Conversions: Enhanced conversion tracking with hashed PII
  • Metrics Aggregation: Campaign performance across date ranges
  • Developer Token: Enterprise-level API access

Use Cases:

  • Automated daily performance reporting
  • Offline conversion import from CRM
  • Custom analytics dashboards
  • Budget optimization workflows
  • Multi-account management
  • ROAS tracking and alerts

Prerequisites

1. Google Ads Account

Requirements:

  • Active Google Ads account
  • Manager account (MCC) recommended for agencies
  • Campaigns with conversion tracking enabled
  • Admin access to Google Ads account

2. Google Cloud Project

Setup Google Cloud:

  1. Go to https://console.cloud.google.com
  2. Create new project or select existing
  3. Enable Google Ads API
  4. Create OAuth 2.0 credentials:
  5. Application type: Web application
  6. Authorized redirect URIs: https://yourapp.basecloudglobal.com/oauth/callback
  7. Note Client ID and Client Secret

3. Google Ads Developer Token

Obtain Developer Token:

  1. Sign in to Google Ads
  2. Navigate to Tools & Settings → Setup → API Center
  3. Apply for Developer Token
  4. For testing: Use test account token
  5. For production: Apply for Basic or Standard access
  6. Approval process: 24-48 hours

Access Levels:

  • Test Account: Limited to test account data
  • Basic: Production access, rate limits apply
  • Standard: Higher limits, requires spending threshold ($10,000+)

4. OAuth Configuration in BaseCloud

Create App Connection:

  1. Navigate to BaseCloud CRM → Settings → Integrations → App Connections
  2. Click + New App Connection
  3. Select Google Ads from dropdown
  4. Enter credentials:
  5. Client ID: From Google Cloud Console
  6. Client Secret: From Google Cloud Console
  7. Developer Token: From Google Ads API Center
  8. Click Authorize with Google
  9. Authorize scope: https://www.googleapis.com/auth/adwords
  10. Select Google Ads account (Manager account if applicable)
  11. Save connection

OAuth Scopes Required:

https://www.googleapis.com/auth/adwords

5. Customer ID and Account Structure

Get Customer IDs:

  • Manager Account (MCC): 10-digit ID without hyphens (e.g., 1234567890)
  • Client Accounts: Sub-account IDs under manager
  • Found in Google Ads top right corner or account selector

Account Hierarchy:

Manager Account (MCC)
├── Client Account 1
├── Client Account 2
└── Client Account 3

For automation: - Use Manager ID for multi-account access - Use specific Account ID for single-account operations


Configuration

Action 1: get_metrics

Retrieve aggregated campaign performance metrics for specified date range.

Field Required Description Example
action Yes Must be "get_metrics" get_metrics
app_connection_id Yes OAuth connection ID Select from dropdown
customer_id Yes Manager/MCC account ID 1234567890
account_id Yes Target Google Ads account 9876543210
metrics_list Yes JSON array of metrics to fetch ["impressions","clicks","cost"]
date_range Yes Date range preset or 'CUSTOM' LAST_30_DAYS
start_date Conditional Start date if date_range='CUSTOM' 2024-01-01
end_date Conditional End date if date_range='CUSTOM' 2024-01-31

Date Range Options:

Preset Description
TODAY Today only
YESTERDAY Yesterday only
LAST_7_DAYS Last 7 days including today
LAST_14_DAYS Last 14 days
LAST_30_DAYS Last 30 days
LAST_90_DAYS Last 90 days
LAST_30_60_DAYS Days 31-60 in the past
THIS_MONTH Current month to date
LAST_MONTH Previous calendar month
CUSTOM Custom date range (requires start_date & end_date)

Available Metrics:

Basic Performance: - impressions - Ad impressions - clicks - Clicks on ads - ctr - Click-through rate (calculated) - average_cpc - Average cost per click - cost - Total spend

Conversions: - conversions - Total conversions - conversions_value - Total conversion value - conversion_rate - Conversion rate (calculated) - cost_per_conversion - Cost per conversion - conversions_from_interactions_rate - Conversion rate from interactions

All Conversions (includes view-through): - all_conversions - all_conversions_value - all_conversions_from_interactions_rate - cost_per_all_conversions - value_per_all_conversions

Impression Share: - search_impression_share - Percentage of eligible impressions received - search_budget_lost_impression_share - Lost due to budget - search_rank_lost_impression_share - Lost due to ad rank

Note: Calculated metrics (ctr, conversion_rate, etc.) are computed post-aggregation.

Output Variables:

task_35001_run              // true/false
task_35001_run_text         // "Metrics fetched."
task_35001_metrics          // Complete metrics object
  task_35001_impressions    // Individual metric values
  task_35001_clicks
  task_35001_ctr
  task_35001_cost
  task_35001_conversions
  // ... all requested metrics

How It Works:

  1. Validates OAuth connection and developer token
  2. Builds GAQL query: SELECT metrics.X FROM campaign WHERE segments.date DURING {range}
  3. Fetches data from Google Ads API v19
  4. Aggregates metrics across all campaigns
  5. Calculates derived metrics (CTR, conversion rate, etc.)
  6. Converts cost from micros to currency (÷ 1,000,000)
  7. Returns unified metrics object

Example Metrics Object:

{
  impressions: 125000,
  clicks: 4500,
  ctr: 3.6,
  cost: 12500.50,
  average_cpc: 2.78,
  conversions: 450,
  conversions_value: 45000.00,
  conversion_rate: 10.0,
  cost_per_conversion: 27.79,
  search_impression_share: 85.5
}

Action 2: upload_offline_conversions

Upload offline conversion events to Google Ads for conversion tracking.

Field Required Description Example
action Yes Must be "upload_offline_conversions" upload_offline_conversions
app_connection_id Yes OAuth connection ID Select from dropdown
customer_id Yes Manager/MCC account ID 1234567890
account_id Yes Target Google Ads account 9876543210
conversion_action Yes Conversion action ID 123456789
Timestamp Yes Conversion datetime (ISO 8601) 2024-02-08T14:30:00+00:00
Value Yes Conversion value 99.99
Currency Yes Currency code (ISO 4217) USD
Consent for ad User Data Yes GDPR consent status GRANTED, DENIED, UNSPECIFIED
Consent for ad personalisation Yes Personalization consent GRANTED, DENIED, UNSPECIFIED

User Identifiers (at least ONE required):

Configure with setting_1 = 'upload_offline_conversions_identifier':

Identifier Description Auto-Hashed
gclid Google Click ID (preferred) No
gbraid iOS SKAN identifier No
wbraid iOS web-to-app identifier No
email Email address Yes (SHA256)
phone Phone number (digits only) Yes (SHA256)
mobile_id Mobile advertising ID No
third_party_user_id Custom user identifier No
address_info Format: "Country Code, Postal Code" No
customer_match_user_list Customer Match user ID No

Additional Optional Fields:

Field Description Example
order_id Transaction/order identifier ORDER-12345

Output Variables:

task_35001_run              // true/false
task_35001_run_text         // "Offline conversion uploaded successfully."
task_35001_result           // Upload result object
  task_35001_result.success // true/false
  task_35001_result.message // Status message

How It Works:

  1. Validates required fields and at least one identifier
  2. Hashes PII (email, phone) with SHA256 automatically
  3. Builds conversion payload with user identifiers
  4. Adds GDPR consent headers
  5. Calls: POST https://googleads.googleapis.com/v19/customers/{accountId}:uploadClickConversions
  6. Returns success status

Click Identifiers vs Enhanced Conversions:

  • With gclid/gbraid/wbraid: Standard click-based conversion
  • Without click identifier: Enhanced conversion with hashed PII

Example Request:

{
  conversions: [{
    conversionAction: "customers/9876543210/conversionActions/123456789",
    conversionDateTime: "2024-02-08T14:30:00+00:00",
    conversionValue: 99.99,
    currencyCode: "USD",
    orderId: "ORDER-12345",
    gclid: "EAIaIQobChMI..." // Or userIdentifiers if no click ID
  }],
  partialFailure: true
}

GDPR Consent Headers:

consent-ad-user-data: GRANTED
consent-ad-personalization: GRANTED

Get Conversion Actions:

Use frontend dropdown or query:

SELECT conversion_action.id, conversion_action.name, conversion_action.type
FROM conversion_action
WHERE conversion_action.status = 'ENABLED'
  AND conversion_action.type IN ('WEBPAGE', 'UPLOAD_CLICKS', 'UPLOAD_CALLS')

Action 3: custom_query

Execute custom GAQL (Google Ads Query Language) queries for advanced reporting.

Field Required Description Example
action Yes Must be "custom_query" custom_query
app_connection_id Yes OAuth connection ID Select from dropdown
customer_id Yes Manager/MCC account ID 1234567890
account_id Yes Target Google Ads account 9876543210
Query Yes GAQL query string See examples below

Output Variables:

task_35001_run              // true/false
task_35001_run_text         // "Custom query executed successfully."
task_35001_query            // Executed query string
task_35001_data             // Array of result objects
task_35001_row_count        // Number of rows returned

GAQL Query Examples:

Get Campaign Names and Performance:

SELECT 
  campaign.id,
  campaign.name,
  campaign.status,
  metrics.impressions,
  metrics.clicks,
  metrics.cost_micros
FROM campaign
WHERE segments.date DURING LAST_30_DAYS
ORDER BY metrics.impressions DESC
LIMIT 100

Get Ad Group Keywords:

SELECT 
  ad_group_criterion.keyword.text,
  ad_group_criterion.keyword.match_type,
  metrics.impressions,
  metrics.clicks,
  metrics.cost_micros
FROM keyword_view
WHERE campaign.id = 12345
  AND segments.date DURING LAST_7_DAYS
ORDER BY metrics.clicks DESC

Get Conversion Actions:

SELECT 
  conversion_action.id,
  conversion_action.name,
  conversion_action.type,
  conversion_action.category,
  conversion_action.status
FROM conversion_action
WHERE conversion_action.status = 'ENABLED'

Get Ad Performance by Device:

SELECT 
  ad_group_ad.ad.id,
  ad_group_ad.ad.name,
  segments.device,
  metrics.impressions,
  metrics.clicks,
  metrics.ctr
FROM ad_group_ad
WHERE segments.date DURING THIS_MONTH
  AND ad_group_ad.status = 'ENABLED'

Get Search Terms Report:

SELECT 
  search_term_view.search_term,
  search_term_view.status,
  metrics.impressions,
  metrics.clicks,
  metrics.conversions
FROM search_term_view
WHERE segments.date DURING LAST_30_DAYS
  AND metrics.impressions > 0
ORDER BY metrics.impressions DESC
LIMIT 500

GAQL Resources:

  • campaign - Campaign-level data
  • ad_group - Ad group data
  • ad_group_ad - Individual ads
  • ad_group_criterion - Keywords, placements
  • keyword_view - Keyword performance
  • search_term_view - Search query performance
  • conversion_action - Conversion definitions
  • customer - Account information

GAQL Segments:

  • segments.date - Date dimension
  • segments.device - Device type (MOBILE, DESKTOP, TABLET)
  • segments.ad_network_type - Network (SEARCH, DISPLAY, YOUTUBE)
  • segments.conversion_action - Conversion breakdown
  • segments.hour - Hour of day

Documentation: https://developers.google.com/google-ads/api/fields/v19


Real-World Examples

Example 1: Daily Performance Email Report

Scenario: Send daily email with yesterday's campaign performance to marketing team.

Workflow:

  1. Trigger: Timer - Daily at 8:00 AM

  2. Task: Google Ads - Get Metrics

    action: get_metrics
    app_connection_id: [Select connection]
    customer_id: 1234567890
    account_id: 9876543210
    metrics_list: ["impressions","clicks","cost","conversions","conversions_value","ctr","average_cpc","cost_per_conversion"]
    date_range: YESTERDAY
    

  3. Task: Variable - Calculate ROAS

    Variable: roas
    Value: {{task_35001_conversions_value}} / {{task_35001_cost}}
    

  4. Task: Email - Send Report

    To: marketing@company.com
    Subject: Google Ads Daily Report - {{yesterday_date}}
    Body:
    📊 Yesterday's Google Ads Performance
    
    Impressions: {{task_35001_impressions}}
    Clicks: {{task_35001_clicks}}
    CTR: {{task_35001_ctr}}%
    
    Cost: ${{task_35001_cost}}
    Average CPC: ${{task_35001_average_cpc}}
    
    Conversions: {{task_35001_conversions}}
    Conversion Value: ${{task_35001_conversions_value}}
    Cost per Conversion: ${{task_35001_cost_per_conversion}}
    
    ROAS: {{roas}}x
    
    ✅ Have a great day!
    

  5. Task: Workflow Note

    Note: Daily Google Ads report sent. ROAS: {{roas}}x
    Type: Marketing
    

Result: Automated daily performance visibility for marketing team.


Example 2: Offline Conversion Import from CRM

Scenario: When deal closes in CRM, upload conversion to Google Ads for ROAS tracking.

Workflow:

  1. Trigger: CRM Event - Deal Won

    Receives: deal_id, deal_value, client_id, gclid (from custom field)
    

  2. Task: If Condition - Has GCLID

    Condition: {{trigger_gclid}} is not empty
    

  3. Task (Inside If): Google Ads - Upload Offline Conversion

    action: upload_offline_conversions
    app_connection_id: [Select connection]
    customer_id: 1234567890
    account_id: 9876543210
    conversion_action: 987654321
    Timestamp: {{trigger_deal_close_date}}T{{trigger_deal_close_time}}+00:00
    Value: {{trigger_deal_value}}
    Currency: USD
    order_id: DEAL-{{trigger_deal_id}}
    Consent for ad User Data: GRANTED
    Consent for ad personalisation: GRANTED
    setting_1: upload_offline_conversions_identifier
    gclid: {{trigger_gclid}}
    

  4. Task (Inside If): Edit Client - Tag

    Field: tags
    Value: Google Ads Conversion Tracked
    Mode: Append
    

  5. Task (Inside If): Workflow Note

    Note: Offline conversion uploaded to Google Ads for deal {{trigger_deal_id}}. Value: ${{trigger_deal_value}}
    Type: Sales
    

  6. Task (Else): Email - Alert Missing GCLID

    To: marketing@company.com
    Subject: ⚠️ Deal Won Without GCLID
    Body: Deal {{trigger_deal_id}} closed without Google Ads tracking.
          Client: {{client_name}}
          Value: ${{trigger_deal_value}}
    
          Please verify UTM parameters on landing pages.
    

Result: Accurate ROAS measurement with offline CRM conversions attributed to Google Ads campaigns.


Example 3: Budget Alert System

Scenario: Alert when daily spend exceeds budget threshold to prevent overspend.

Workflow:

  1. Trigger: Timer - Every 2 hours during business hours

  2. Task: Google Ads - Get Metrics

    action: get_metrics
    metrics_list: ["cost"]
    date_range: TODAY
    

  3. Task: Variable - Daily Budget Threshold

    Variable: daily_budget
    Value: 500
    

  4. Task: If Condition - Budget Exceeded

    Condition: {{task_35001_cost}} greater than {{daily_budget}}
    

  5. Task (Inside If): Email - Alert Marketing Team

    To: marketing@company.com, cfo@company.com
    Subject: 🚨 Google Ads Budget Alert
    Body:
    ⚠️ Daily budget threshold exceeded!
    
    Current Spend Today: ${{task_35001_cost}}
    Daily Budget: ${{daily_budget}}
    Overspend: ${{task_35001_cost - daily_budget}}
    
    Time: {{current_time}}
    
    Action Required: Review campaigns and adjust bids/budgets if needed.
    

  6. Task (Inside If): MySQL - Log Alert

    INSERT INTO budget_alerts (date, spend, threshold, alert_time)
    VALUES (CURDATE(), {{task_35001_cost}}, {{daily_budget}}, NOW())
    

  7. Task: Workflow Note

    Note: Budget check completed. Spend: ${{task_35001_cost}}
    

Result: Proactive budget management prevents unexpected overspend.


Example 4: Advanced Campaign Analysis with GAQL

Scenario: Analyze campaign performance by device and time of day for optimization insights.

Workflow:

  1. Trigger: Manual Button - Run Analysis

  2. Task: Google Ads - Custom Query (Campaigns by Device)

    action: custom_query
    Query:
    SELECT 
      campaign.name,
      segments.device,
      metrics.impressions,
      metrics.clicks,
      metrics.cost_micros,
      metrics.conversions
    FROM campaign
    WHERE segments.date DURING LAST_30_DAYS
      AND campaign.status = 'ENABLED'
    ORDER BY metrics.impressions DESC
    

  3. Task: Variable - Store Campaign Data

    Variable: campaign_device_data
    Value: {{task_35001_data}}
    

  4. Task: Google Ads - Custom Query (Search Terms)

    action: custom_query
    Query:
    SELECT 
      search_term_view.search_term,
      metrics.impressions,
      metrics.clicks,
      metrics.ctr,
      metrics.conversions,
      metrics.cost_micros
    FROM search_term_view
    WHERE segments.date DURING LAST_30_DAYS
      AND metrics.impressions > 10
    ORDER BY metrics.clicks DESC
    LIMIT 100
    

  5. Task: Loop - Process Each Search Term

    Loop through {{task_35001_data}}
    

  6. Task (Inside Loop): If Condition - High Converting Term

    Condition: {{loop_item_conversions}} greater than 5
          AND {{loop_item_ctr}} greater than 5.0
    

  7. Task (Inside If): MySQL - Log High Performer

    INSERT INTO high_performing_keywords (search_term, clicks, ctr, conversions, cost, date_analyzed)
    VALUES (
      '{{loop_item_search_term}}',
      {{loop_item_clicks}},
      {{loop_item_ctr}},
      {{loop_item_conversions}},
      {{loop_item_cost_micros / 1000000}},
      NOW()
    )
    

  8. Task: Email - Send Analysis Report

    To: marketing@company.com
    Subject: Google Ads Performance Analysis
    Body:
    📊 Campaign Analysis Complete
    
    Top Performing Search Terms: {{high_performer_count}}
    Device Breakdown: [Summary from campaign_device_data]
    
    See attached MySQL data for detailed insights.
    
    Recommendations:
    1. Increase bids on high-converting search terms
    2. Optimize device targeting based on performance
    3. Review low-CTR campaigns for improvements
    

Result: Data-driven optimization insights for campaign management.


Example 5: Multi-Account Reporting for Agencies

Scenario: Agency managing multiple client Google Ads accounts needs consolidated reporting.

Workflow:

  1. Trigger: Timer - Weekly on Monday 9:00 AM

  2. Task: MySQL Query - Get Client Accounts

    SELECT 
      client_id,
      client_name,
      google_ads_customer_id,
      google_ads_account_id,
      google_ads_app_connection_id
    FROM clients
    WHERE google_ads_active = 1
    

  3. Task: Loop - Process Each Client

    Loop through MySQL results
    

  4. Task (Inside Loop): Google Ads - Get Metrics

    action: get_metrics
    app_connection_id: {{loop_item_google_ads_app_connection_id}}
    customer_id: {{loop_item_google_ads_customer_id}}
    account_id: {{loop_item_google_ads_account_id}}
    metrics_list: ["impressions","clicks","cost","conversions","conversions_value"]
    date_range: LAST_7_DAYS
    

  5. Task (Inside Loop): MySQL - Store Weekly Metrics

    INSERT INTO weekly_google_ads_reports 
    (client_id, week_start, impressions, clicks, cost, conversions, conversion_value, created_date)
    VALUES (
      {{loop_item_client_id}},
      DATE_SUB(CURDATE(), INTERVAL 7 DAY),
      {{task_35001_impressions}},
      {{task_35001_clicks}},
      {{task_35001_cost}},
      {{task_35001_conversions}},
      {{task_35001_conversions_value}},
      NOW()
    )
    

  6. Task (Inside Loop): Delay 2 seconds

    Reason: Rate limiting prevention
    

  7. Task: MySQL Query - Get Summary Stats

    SELECT 
      SUM(impressions) as total_impressions,
      SUM(clicks) as total_clicks,
      SUM(cost) as total_cost,
      SUM(conversions) as total_conversions,
      SUM(conversion_value) as total_value,
      COUNT(DISTINCT client_id) as client_count
    FROM weekly_google_ads_reports
    WHERE week_start = DATE_SUB(CURDATE(), INTERVAL 7 DAY)
    

  8. Task: Email - Agency Summary Report

    To: agency-team@company.com
    Subject: 📊 Weekly Google Ads Summary - All Clients
    Body:
    Agency Performance Summary
    Week: {{week_start_date}} to {{week_end_date}}
    
    Clients Managed: {{mysql_result_client_count}}
    
    📈 Totals:
    Impressions: {{mysql_result_total_impressions}}
    Clicks: {{mysql_result_total_clicks}}
    Spend: ${{mysql_result_total_cost}}
    Conversions: {{mysql_result_total_conversions}}
    Conversion Value: ${{mysql_result_total_value}}
    
    Overall ROAS: {{mysql_result_total_value / mysql_result_total_cost}}x
    
    See database for per-client breakdowns.
    

Result: Consolidated multi-account reporting for agency portfolio management.


Troubleshooting

Error: "No app connection selected"

Cause: OAuth connection not configured

Solutions:

  1. Go to Settings → Integrations → App Connections
  2. Create Google Ads connection
  3. Enter Client ID, Client Secret, and Developer Token
  4. Complete OAuth authorization
  5. Select connection in task dropdown

Error: "Developer token required"

Cause: Missing or invalid developer token in OAuth config

Solutions:

  1. Obtain developer token from Google Ads API Center
  2. Edit app connection in BaseCloud
  3. Add developer token to OAuth configuration
  4. For testing: Use test account token
  5. For production: Apply for Basic/Standard access

Error: "Invalid customer ID"

Cause: Customer ID format incorrect or inaccessible

Solutions:

  1. Use 10-digit ID without hyphens: 1234567890 (not 123-456-7890)
  2. Verify account access in Google Ads
  3. Use Manager Account (MCC) ID for multi-account access
  4. Check OAuth connection has access to specified customer
  5. Remove any special characters or spaces

Error: "Token expired" or 401 Unauthorized

Cause: OAuth access token expired

Solutions:

  1. BaseCloud automatically refreshes tokens
  2. If error persists, re-authorize app connection:
  3. Settings → App Connections → Edit
  4. Click Re-authorize with Google
  5. Verify OAuth scope is correct: https://www.googleapis.com/auth/adwords
  6. Check refresh token hasn't been revoked

Metrics List Empty or Invalid

Cause: metrics_list field is empty array '[]' or invalid JSON

Solutions:

  1. Provide at least one metric: ["impressions"]
  2. Use valid JSON array format with quotes
  3. Check metric names match available options
  4. Remove spaces from metric names
  5. Valid example: ["impressions","clicks","cost"]

Custom Query Returns No Data

Cause: GAQL query syntax error or no matching data

Solutions:

  1. Test query in Google Ads Query Builder first
  2. Verify resource names (e.g., campaign, not campaigns)
  3. Check date range has data
  4. Validate WHERE clause filters
  5. Use LIMIT to prevent large result sets
  6. Check API field reference: https://developers.google.com/google-ads/api/fields/v19

Offline Conversion Upload Failed

Cause: Missing required identifiers or invalid format

Solutions:

  1. Provide at least ONE identifier (gclid preferred)
  2. Verify conversion action ID is correct (get from dropdown or custom query)
  3. Check timestamp format: ISO 8601 with timezone (2024-02-08T14:30:00+00:00)
  4. Validate value is numeric (no currency symbols)
  5. Use valid currency code (USD, EUR, GBP, etc.)
  6. Email/phone are auto-hashed, provide plain text
  7. Check consent fields are: GRANTED, DENIED, or UNSPECIFIED

Error: "Conversion action not found"

Cause: Invalid conversion action ID or not uploadable type

Solutions:

  1. Get conversion actions via custom query:
    SELECT conversion_action.id, conversion_action.name, conversion_action.type
    FROM conversion_action
    WHERE conversion_action.status = 'ENABLED'
    
  2. Use conversion actions with types: WEBPAGE, UPLOAD_CLICKS, UPLOAD_CALLS
  3. Cannot use PHONE_CALL_LEAD or STORE_VISIT types for API upload
  4. Verify conversion action belongs to correct account

Rate Limiting / Quota Exceeded

Cause: Exceeded Google Ads API rate limits

Solutions:

  1. Standard Access Limits:
  2. 15,000 operations per day
  3. Requests count against quota

  4. Immediate Actions:

  5. Add delays in bulk processing loops (2-5 seconds)
  6. Reduce frequency of metric fetches
  7. Cache results when possible

  8. Long-term:

  9. Apply for Standard Access (requires $10,000+ spend)
  10. Use batch operations where possible
  11. Implement exponential backoff on errors
  12. Monitor quota usage in Google Cloud Console

Permission Denied on Specific Account

Cause: OAuth token doesn't have access to target account

Solutions:

  1. Verify account hierarchy:
  2. Manager account must link to client accounts
  3. User must have access to manager account
  4. Check Google Ads permissions:
  5. Navigate to Tools → Access & Security → Users
  6. Verify email has Admin or Standard access
  7. Re-authorize OAuth connection
  8. Use correct customer_id (manager) and account_id (client)

Best Practices

Authentication Management

  1. Developer Token:
  2. Store securely in OAuth config
  3. Use test token for development/staging
  4. Apply for production access before launch
  5. Monitor approval status in API Center

  6. OAuth Connections:

  7. Create separate connections for dev/staging/production
  8. Use descriptive names: "Google Ads - Main Account", "Google Ads - Client ABC"
  9. Document which connection accesses which accounts

  10. Token Refresh:

  11. BaseCloud handles automatic refresh
  12. Monitor for refresh failures
  13. Re-authorize if persistent issues

Metrics Strategy

  1. Metric Selection:
  2. Request only needed metrics to reduce processing time
  3. Use calculated metrics (CTR, conversion rate) instead of computing manually
  4. Avoid mixing incompatible metrics in same query

  5. Date Ranges:

  6. Use presets when possible (faster than custom)
  7. For historical analysis, use custom ranges
  8. Be aware of data freshness (typically 3-hour delay)

  9. Aggregation:

  10. Metrics are aggregated across all campaigns by default
  11. Use custom queries for campaign-level breakdown
  12. Consider impression share metrics for competitive analysis

GAQL Best Practices

  1. Query Optimization:
  2. Select only needed fields
  3. Use WHERE clauses to filter data
  4. Add LIMIT to prevent oversized results
  5. Order by relevant metrics

  6. Resource Selection:

  7. Use campaign for campaign-level data
  8. Use ad_group_ad for ad-level data
  9. Use keyword_view for keyword performance
  10. Use search_term_view for actual search queries

  11. Segmentation:

  12. Add segments.date for daily breakdown
  13. Use segments.device for device analysis
  14. Include segments.ad_network_type for network split

Offline Conversion Best Practices

  1. Identifier Strategy:
  2. Preferred: Use gclid (Google Click ID)
  3. Fallback: Enhanced conversions with email/phone
  4. Store gclid in CRM on form submission
  5. Validate identifier exists before upload

  6. Data Quality:

  7. Use accurate conversion timestamps
  8. Provide actual conversion value (not estimated)
  9. Include order IDs for deduplication
  10. Set appropriate consent values

  11. Conversion Actions:

  12. Create specific actions for different conversion types
  13. Use consistent naming: "Purchase - Website", "Lead - Phone"
  14. Set appropriate counting methods (One per click vs Every)
  15. Configure lookback windows appropriately

Performance Optimization

  1. Caching:
  2. Cache metric results for dashboards (hourly refresh)
  3. Store conversion action lists (reload daily)
  4. Cache account hierarchy (reload weekly)

  5. Rate Limiting:

  6. Add 2-5 second delays in multi-account loops
  7. Batch operations when possible
  8. Schedule large queries during off-peak
  9. Implement exponential backoff for retries

  10. Error Handling:

  11. Wrap critical queries in If Conditions
  12. Log failures for troubleshooting
  13. Provide fallback workflows
  14. Alert admins on persistent failures

Reporting Strategy

  1. Automated Reports:
  2. Daily performance summary (yesterday's data)
  3. Weekly trends analysis (7-day rolling)
  4. Monthly campaign reviews (full month)
  5. Real-time alerts (budget, performance)

  6. Data Storage:

  7. Log metrics to MySQL for historical trends
  8. Create time-series data for visualization
  9. Archive raw query results for auditing
  10. Maintain client-level reporting tables

  11. Stakeholder Communication:

  12. Executive summary: High-level metrics (ROAS, conversions)
  13. Marketing team: Detailed campaign performance
  14. Finance: Spend tracking and budget adherence
  15. Clients: Campaign-specific results

FAQ

Q: What's the difference between customer_id and account_id?

A: - customer_id: Manager Account (MCC) ID - top-level account managing others - account_id: Specific Google Ads account where ads run - For single accounts: Both can be same ID - For agencies: customer_id = MCC, account_id = client account

Q: Do I need a Manager Account (MCC)?

A: - Not required for single account management - Recommended for agencies or multi-account setups - Benefits: Centralized billing, cross-account reporting, user management

Q: How long does it take for data to appear?

A: - Performance data: Typically 3 hours delay - Conversion data: Can take 24-48 hours - Offline conversions: Usually within a few hours of upload

Q: What's a developer token and how do I get one?

A: Developer token authenticates API access. Get from Google Ads → Tools → API Center. Test tokens work immediately; production requires application approval (24-48 hours).

Q: Can I modify campaigns via API?

A: This task focuses on reporting and conversion upload. Campaign modification requires additional actions not currently implemented. Use Google Ads UI or consider custom development.

Q: What are micros and why does cost use them?

A: Google Ads API returns costs in micros (1/1,000,000 of currency). BaseCloud automatically converts: cost_micros / 1,000,000 = actual cost.

Q: How accurate is GAQL query execution?

A: GAQL queries execute directly against Google Ads API with same accuracy as Google Ads UI. Results match reporting UI but may have slight timestamp differences.

Q: Can I track phone call conversions?

A: Yes, using offline conversion upload with phone call conversion action. Store call details in CRM and upload with appropriate conversion action ID.

Q: What happens if I exceed rate limits?

A: API returns quota exceeded error. Implement delays between requests (2-5 seconds) and apply for Standard Access for higher limits.

Q: Can I access competitor data?

A: No, API only accesses accounts you manage. Use impression share metrics to gauge competitive landscape.

Q: How do I handle multi-currency accounts?

A: Specify currency in offline conversion uploads. For metrics, Google Ads converts to account currency automatically.

Q: Can I export data to Google Sheets?

A: Yes, use Google Sheets task after getting metrics. Store data in variables and write to sheets.



Technical Details

  • Type ID: 35
  • Function: taskGoogleAds() in automationService.js (lines 9795-10046)
  • Service: googleAdsService.js (936 lines)
  • API Version: Google Ads API v19
  • NPM Package: google-ads-api v12+
  • Authentication: OAuth 2.0 + Developer Token
  • Scope: https://www.googleapis.com/auth/adwords
  • Output Prefix: task_35001_*
  • Rate Limits: 15,000 operations/day (Standard Access)
  • GAQL Documentation: https://developers.google.com/google-ads/api/docs/query/overview
  • API Reference: https://developers.google.com/google-ads/api/reference/rpc/v19