Google Ads API Setup Instructions

Step-by-Step Guide for Testing API Access


โœ… What You Already Have

Based on your current .env file, you have:


๐Ÿ”ง Step 1: Add Missing Environment Variable

You need to add your Google Ads Customer ID to your .env file.

Finding Your Customer ID:

  1. Go to: https://ads.google.com
  2. Look in the top right corner - you'll see your customer ID
  3. It should look like: 623-323-9884 (your MCC ID)
  4. OR if you're managing a specific account, use that account's ID

Add to .env:

# Add this line to your .env file
GOOGLE_ADS_CUSTOMER_ID="623-323-9884"

Note: The API will automatically remove the dashes, so you can include them or not.


๐Ÿ” Step 2: OAuth Setup (Required Before Testing)

The Google Ads API requires OAuth 2.0 authentication. You need to authorize your application.

Option A: Use Search Console OAuth (If Already Authorized)

If you've already authorized Search Console, you might be able to reuse those credentials IF:

Option B: Create New Google Ads OAuth Authorization

You'll need to set up an OAuth flow similar to Search Console:

  1. Update OAuth Scope in Google Cloud Console:

  2. Create Authorization Route (following Search Console pattern):

    # Add to config/routes.rb
    namespace :admin do
      namespace :oauth do
        get 'authorize/google_ads', to: 'oauth#authorize_google_ads'
        get 'callback/google_ads', to: 'oauth#callback_google_ads'
      end
    end
    
  3. Update OAuth Controller (mirror Search Console implementation)

  4. Authorize the Application:


๐Ÿงช Step 3: Test API Access

Test Script 1: Verify Credentials

Create and run this test script:

# test/verify_google_ads_credentials.rb
require_relative '../config/environment'
require 'google/ads/google_ads'

puts "=" * 60
puts "Google Ads API Credentials Verification"
puts "=" * 60
puts ""

# Check environment variables
puts "Checking environment variables..."
required_vars = %w[
  GOOGLE_OAUTH_CLIENT_ID
  GOOGLE_OAUTH_CLIENT_SECRET
  GOOGLE_ADS_DEVELOPER_TOKEN
  GOOGLE_ADS_CUSTOMER_ID
]

required_vars.each do |var|
  value = ENV[var]
  if value.present?
    puts "  โœ“ #{var}: #{value[0..15]}..." # Show first 16 chars
  else
    puts "  โœ— #{var}: MISSING!"
  end
end

puts ""
puts "Checking OAuth credentials in database..."
oauth_cred = OauthCredential.for_provider_and_user(
  provider: "google_ads",
  user_id: "default"
)

if oauth_cred.persisted?
  puts "  โœ“ OAuth record found"
  puts "    - Has refresh token: #{oauth_cred.refresh_token.present?}"
  puts "    - Token expires at: #{oauth_cred.expires_at}"
  puts "    - Is expired: #{oauth_cred.expired?}"
else
  puts "  โœ— No OAuth credentials found"
  puts "    โ†’ You need to authorize at: /admin/oauth/authorize/google_ads"
end

puts ""
puts "=" * 60

Run it:

ruby test/verify_google_ads_credentials.rb

Test Script 2: Test API Connection

Once credentials are verified, test actual API access:

# test/test_google_ads_api_connection.rb
require_relative '../config/environment'
require 'google/ads/google_ads'

puts "=" * 60
puts "Google Ads API Connection Test"
puts "=" * 60
puts ""

begin
  # Get OAuth credentials
  oauth_cred = OauthCredential.for_provider_and_user(
    provider: "google_ads",
    user_id: "default"
  )

  unless oauth_cred.persisted? && oauth_cred.refresh_token.present?
    puts "โœ— No OAuth credentials found!"
    puts "  โ†’ Authorize at: /admin/oauth/authorize/google_ads"
    exit 1
  end

  puts "Creating Google Ads client..."
  client = Google::Ads::GoogleAds::GoogleAdsClient.new do |config|
    config.client_id = ENV.fetch('GOOGLE_OAUTH_CLIENT_ID')
    config.client_secret = ENV.fetch('GOOGLE_OAUTH_CLIENT_SECRET')
    config.developer_token = ENV.fetch('GOOGLE_ADS_DEVELOPER_TOKEN')
    config.refresh_token = oauth_cred.refresh_token
    config.login_customer_id = ENV.fetch('GOOGLE_ADS_CUSTOMER_ID').delete('-')
  end

  puts "โœ“ Client created successfully"
  puts ""

  # Test 1: List accessible customers
  puts "Test 1: Listing accessible customer accounts..."
  customer_service = client.service.customer
  customer_id = ENV.fetch('GOOGLE_ADS_CUSTOMER_ID').delete('-')

  query = <<~QUERY
    SELECT
      customer.id,
      customer.descriptive_name,
      customer.currency_code,
      customer.time_zone
    FROM customer
    WHERE customer.id = #{customer_id}
  QUERY

  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query
  )

  if response.any?
    puts "โœ“ Successfully connected to Google Ads API!"
    response.each do |row|
      customer = row.customer
      puts ""
      puts "  Account Details:"
      puts "    Customer ID: #{customer.id}"
      puts "    Name: #{customer.descriptive_name}"
      puts "    Currency: #{customer.currency_code}"
      puts "    Timezone: #{customer.time_zone}"
    end
  else
    puts "โœ— No customer data returned"
  end

  puts ""
  puts "Test 2: Fetching campaign data..."

  query = <<~QUERY
    SELECT
      campaign.id,
      campaign.name,
      campaign.status,
      campaign.advertising_channel_type
    FROM campaign
    ORDER BY campaign.name
    LIMIT 5
  QUERY

  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query
  )

  if response.any?
    puts "โœ“ Successfully fetched campaign data!"
    puts ""
    puts "  Your Campaigns:"
    response.each do |row|
      campaign = row.campaign
      puts "    - #{campaign.name} (#{campaign.status})"
      puts "      ID: #{campaign.id}"
      puts "      Type: #{campaign.advertising_channel_type}"
    end
  else
    puts "  โš  No campaigns found (account might be empty)"
  end

  puts ""
  puts "=" * 60
  puts "โœ… ALL TESTS PASSED!"
  puts "=" * 60

rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
  puts ""
  puts "=" * 60
  puts "โœ— Google Ads API Error"
  puts "=" * 60
  puts ""
  puts "Error: #{e.message}"
  puts ""

  e.failure.errors.each do |error|
    puts "Error code: #{error.error_code.error_code}"
    puts "Error message: #{error.message}"
    puts ""
  end
rescue => e
  puts ""
  puts "=" * 60
  puts "โœ— Unexpected Error"
  puts "=" * 60
  puts ""
  puts "#{e.class}: #{e.message}"
  puts ""
  puts e.backtrace.first(5)
end

Run it:

ruby test/test_google_ads_api_connection.rb

๐Ÿ“Š Expected Test Results

โœ… Success Looks Like:

==============================================================
Google Ads API Connection Test
==============================================================

Creating Google Ads client...
โœ“ Client created successfully

Test 1: Listing accessible customer accounts...
โœ“ Successfully connected to Google Ads API!

  Account Details:
    Customer ID: 6233239884
    Name: Quarry Rentals
    Currency: USD
    Timezone: America/Los_Angeles

Test 2: Fetching campaign data...
โœ“ Successfully fetched campaign data!

  Your Campaigns:
    - LA Dumpster Rental - Search (ENABLED)
      ID: 12345678901
      Type: SEARCH
    - OC Roll-Off Service (ENABLED)
      ID: 12345678902
      Type: SEARCH

==============================================================
โœ… ALL TESTS PASSED!
==============================================================

โŒ Common Errors and Solutions:

Error: "AUTHENTICATION_ERROR - User doesn't have permission to access customer"

Error: "DEVELOPER_TOKEN_NOT_APPROVED"

Error: "INVALID_CUSTOMER_ID"

Error: "No OAuth credentials found"


๐Ÿš€ After Successful Testing

Once tests pass, you're ready to:

  1. Run database migrations:

    bin/rails db:migrate
    
  2. Create the models, services, and controllers (as outlined in google_ads_implementation_guide.md)

  3. Test data sync:

    service = GoogleAdsService.new
    result = service.sync_all(start_date: 7.days.ago, end_date: Date.yesterday)
    puts result.inspect
    
  4. Deploy to production with updated environment variables


๐Ÿ”’ Production Deployment Checklist

Before deploying:


๐Ÿ“ Quick Reference

Your Google Ads Credentials:

API Scopes Required:

Useful Links:


Need Help? If you encounter issues, check:

  1. API Center for approval status
  2. OAuth consent screen has correct scopes
  3. Customer ID matches your actual account
  4. Developer token is not expired