Google Ads Troubleshooting & Debugging
Comprehensive diagnostic guide for resolving Google Ads conversion tracking, tag implementation, and campaign issues.
Symptom Library
Conversion Tracking Issues
- Conversions not recording - Zero conversions despite traffic
- Delayed conversions - Conversions appearing 24-72 hours late
- Conversion value discrepancies - Mismatches with actual revenue
- Duplicate conversions - Same conversion counted multiple times
- Partial conversions - Some conversions missing from reports
Tag Implementation Issues
- Tag not firing - Google Tag not loading on pages
- Tag firing on wrong pages - Conversion tag on non-conversion pages
- Multiple tags detected - Duplicate tags causing conflicts
- gtag.js vs analytics.js conflicts - Legacy tag conflicts
- Tag Assistant showing errors - Tag implementation errors
Enhanced Conversions Issues
- Partial match quality - Low match rates for enhanced conversions
- Missing user data - Customer info not being sent
- Hashing errors - Incorrect data hashing implementation
- Consent mode conflicts - Enhanced conversions blocked by consent
Auto-Tagging Issues
- GCLID not captured - Click IDs missing from URLs
- UTM parameter conflicts - Auto-tagging overriding manual UTMs
- Cross-domain tracking failures - GCLIDs lost on domain changes
- Session attribution errors - Incorrect source attribution
Campaign Performance Issues
- Ad disapprovals - Policy violations blocking ads
- Low quality scores - High CPCs due to low QS
- Budget limitations - Campaigns limited by budget
- Bid strategy not learning - Smart bidding stuck in learning
- Impression share losses - Missing impressions due to rank/budget
Investigation Workflow
Level 1: Quick Diagnostics (5 minutes)
Step 1: Check Conversion Status
1. Google Ads > Tools > Conversions
2. Check "Status" column:
- "Recording conversions" (Green) = Working
- "No recent conversions" (Yellow) = Warning
- "Unverified" (Red) = Not working
3. Review "Last received" timestamp
Step 2: Tag Assistant Verification
1. Install Google Tag Assistant extension
2. Visit conversion page
3. Click extension icon
4. Verify:
- Google tag detected (green)
- Conversion event fires on action
- No errors or warnings
Step 3: Recent Conversions Check
1. Google Ads > Campaigns
2. Add columns: Conversions, Conv. value
3. Compare last 7 days to prior period
4. Look for sudden drops (>30%)
Level 2: Deep Diagnostics (15-30 minutes)
Tag Implementation Analysis
- Inspect Tag Code
<!-- Verify global site tag present -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-123456789"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'AW-123456789');
</script>
<!-- Verify conversion event tag -->
<script>
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEfGhIjKlMnOpQr',
'value': 99.99,
'currency': 'USD',
'transaction_id': 'ORDER_12345'
});
</script>
- Network Request Inspection
1. Chrome DevTools > Network tab
2. Filter: "google-analytics.com/collect" or "googleadservices.com"
3. Trigger conversion action
4. Verify request sent (Status 200)
5. Check request payload includes:
- Conversion ID
- Conversion label
- Value and currency (if applicable)
- Transaction ID (for deduplication)
- DataLayer Validation
// Console check for dataLayer
console.log(window.dataLayer);
// Should show array with events
// Example output:
[
{0: 'js', 1: Date},
{0: 'config', 1: 'AW-123456789'},
{0: 'event', 1: 'conversion', 2: {...}}
]
Conversion Attribution Analysis
1. Google Ads > Tools > Attribution
2. Review attribution model settings
3. Check attribution window:
- Click-through: 30-90 days
- View-through: 1-30 days
4. Compare different attribution models
Enhanced Conversions Verification
// Check if enhanced conversions data is sent
gtag('config', 'AW-123456789', {
'phone_number': '+1234567890',
'email': 'customer@example.com',
'address': {
'first_name': 'John',
'last_name': 'Doe',
'street': '123 Main St',
'city': 'New York',
'region': 'NY',
'postal_code': '10001',
'country': 'US'
}
});
// Verify data is hashed in network request
// Check DevTools > Network > google-analytics.com/collect
// Look for &em= (hashed email) parameter
Level 3: Advanced Diagnostics (30-60 minutes)
GCLID Capture Testing
// Check if GCLID is being captured
function getGCLID() {
const urlParams = new URLSearchParams(window.location.search);
const gclid = urlParams.get('gclid');
console.log('GCLID present:', !!gclid);
console.log('GCLID value:', gclid);
// Check if stored in cookie
const gclidCookie = document.cookie.match(/gclid=([^;]+)/);
console.log('GCLID cookie:', gclidCookie?.[1] || 'Not found');
return gclid;
}
getGCLID();
Offline Conversion Import Testing
1. Create test conversion in Google Ads
2. Use API or manual upload
3. Verify GCLID matches clicked ad
4. Check for import errors in UI
5. Validate conversion appears within 24 hours
Consent Mode Diagnostics
// Check consent mode status
gtag('consent', 'default', {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
});
// Check current consent state
console.log('Consent state:', window.dataLayer.filter(
item => item[0] === 'consent'
));
// Update consent after user acceptance
gtag('consent', 'update', {
'ad_storage': 'granted',
'analytics_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
});
Common Issues & Solutions
Issue 1: Conversions Not Recording
Symptoms:
- Zero conversions in Google Ads
- Tag fires but no conversions appear
- "Unverified" status in Conversions page
Diagnostic Steps:
- Verify Tag Placement
<!-- WRONG: Event tag without global tag -->
<script>
gtag('event', 'conversion', {'send_to': 'AW-123456789/AbCdEf'});
</script>
<!-- CORRECT: Global tag + event tag -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-123456789"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'AW-123456789');
</script>
<script>
gtag('event', 'conversion', {'send_to': 'AW-123456789/AbCdEf'});
</script>
- Check Conversion Action Status
Google Ads > Tools > Conversions
- Status must be "Recording conversions"
- Not "Removed" or "Paused"
- Verify Conversion Window
Recent conversions may take up to 3 hours to appear
Offline conversions can take 24-48 hours
Check "All conversions" column (includes modeling)
Solutions:
// Ensure gtag function exists before calling
if (typeof gtag !== 'undefined') {
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEfGhIjKl',
'value': 1.0,
'currency': 'USD'
});
} else {
console.error('gtag not loaded - conversion not tracked');
}
Issue 2: Conversion Value Discrepancies
Symptoms:
- Google Ads shows different revenue than actual
- Values in wrong currency
- Decimal precision issues
Solutions:
Currency Consistency
// WRONG: Mixed currencies
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEf',
'value': 99.99,
'currency': 'EUR' // But value is in USD
});
// CORRECT: Match Google Ads account currency
const accountCurrency = 'USD';
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEf',
'value': parseFloat(orderTotal.toFixed(2)),
'currency': accountCurrency
});
Transaction Deduplication
// Prevent double-counting with transaction_id
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEf',
'value': 99.99,
'currency': 'USD',
'transaction_id': 'ORDER_' + orderId // Required for deduplication
});
Value Calculation
// Include tax and shipping or not (be consistent)
const subtotal = 100.00;
const tax = 8.00;
const shipping = 5.00;
// Option 1: Transaction value only
const conversionValue = subtotal;
// Option 2: Total including tax/shipping
const conversionValue = subtotal + tax + shipping;
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEf',
'value': conversionValue,
'currency': 'USD',
'transaction_id': orderId
});
Issue 3: Enhanced Conversions Not Working
Symptoms:
- "Partial" match quality in Google Ads
- Low match rates shown in reporting
- Customer data not being sent
Solutions:
1. Implement Enhanced Conversions
// Method 1: Automatic (recommended)
gtag('set', 'user_data', {
"email": "customer@example.com",
"phone_number": "+12345678900",
"address": {
"first_name": "John",
"last_name": "Doe",
"street": "123 Main St",
"city": "New York",
"region": "NY",
"postal_code": "10001",
"country": "US"
}
});
// Method 2: Manual (code mode)
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEf',
'value': 99.99,
'currency': 'USD',
'transaction_id': 'ORDER_12345',
'email': 'customer@example.com',
'phone_number': '+12345678900',
'first_name': 'John',
'last_name': 'Doe',
'home_address': {
'street': '123 Main St',
'city': 'New York',
'region': 'NY',
'postal_code': '10001',
'country': 'US'
}
});
2. Server-Side Implementation (WordPress)
// Collect user data server-side
function google_ads_enhanced_conversion_data($order_id) {
$order = wc_get_order($order_id);
$enhanced_data = array(
'email' => $order->get_billing_email(),
'phone_number' => $order->get_billing_phone(),
'first_name' => $order->get_billing_first_name(),
'last_name' => $order->get_billing_last_name(),
'home_address' => array(
'street' => $order->get_billing_address_1(),
'city' => $order->get_billing_city(),
'region' => $order->get_billing_state(),
'postal_code' => $order->get_billing_postcode(),
'country' => $order->get_billing_country()
)
);
// Output to dataLayer
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'enhanced_conversion_data',
'user_data': <?php echo json_encode($enhanced_data); ?>
});
</script>
<?php
}
add_action('woocommerce_thankyou', 'google_ads_enhanced_conversion_data');
3. Data Quality Requirements
At minimum, provide ONE of:
- Email (most valuable)
- Phone number
- First name + Last name + Postal code
Format requirements:
- Email: lowercase, trimmed
- Phone: E.164 format (+country code)
- Names: lowercase, no special characters
- Postal code: no spaces
- Country: ISO 3166-1 alpha-2 (US, GB, etc.)
Issue 4: Auto-Tagging Problems
Symptoms:
- GCLIDs missing from landing page URLs
- Source showing as "direct" instead of "google/cpc"
- Offline conversion imports failing
Solutions:
1. Enable Auto-Tagging
Google Ads > Settings > Account settings
Enable "Auto-tagging"
2. Preserve GCLID Across Pages
// Store GCLID on landing
function storeGCLID() {
const urlParams = new URLSearchParams(window.location.search);
const gclid = urlParams.get('gclid');
if (gclid) {
// Store in sessionStorage
sessionStorage.setItem('gclid', gclid);
// Store in cookie (90 days)
document.cookie = `gclid=${gclid}; max-age=${90 * 24 * 60 * 60}; path=/`;
console.log('GCLID stored:', gclid);
}
}
// Retrieve GCLID for conversion
function getStoredGCLID() {
return sessionStorage.getItem('gclid') ||
document.cookie.match(/gclid=([^;]+)/)?.[1];
}
// Use on conversion page
const gclid = getStoredGCLID();
if (gclid) {
// Send with offline conversion import
console.log('GCLID for conversion:', gclid);
}
3. Handle UTM Parameter Conflicts
// Auto-tagging with manual UTMs
// Google Ads auto-tagging will ADD gclid, not replace UTMs
// If you need both, allow override in Google Analytics
// GA4 config:
gtag('config', 'G-XXXXXXXXXX', {
'allow_google_signals': true,
'allow_ad_personalization_signals': true
});
4. Cross-Domain GCLID Passing
// Configure linker for cross-domain tracking
gtag('set', 'linker', {
'domains': ['example.com', 'checkout.example.com'],
'accept_incoming': true
});
// Or for specific links
gtag('set', 'linker', {
'domains': ['checkout.example.com']
});
// Manually decorate links
function decorateLink(url) {
if (typeof gtag !== 'undefined') {
return gtag('linker:decorate', url);
}
return url;
}
Issue 5: Ad Disapprovals
Common Policy Violations:
1. Destination Mismatch
Issue: Ad goes to different URL than display URL
Solution:
- Ensure display URL matches domain of final URL
- Check for redirects changing domain
- Update display URL to match final destination
2. Malicious or Unwanted Software
Issue: Site flagged for malware
Solution:
- Run Google Safe Browsing check
- Scan site with security tools
- Request review after cleanup
3. Circumventing Systems
Issue: Cloaking or misleading content
Solution:
- Ensure ads and landing pages are consistent
- No hidden text or misleading redirects
- Same content for all users/bots
4. Restricted Content
Issue: Prohibited products or services
Solution:
- Review Google Ads policies
- Remove restricted content
- Request certification if applicable (e.g., healthcare)
Issue 6: Low Conversion Rates
Diagnostic Questions:
Is the conversion action correctly defined?
- Check: Does it match actual conversion goal?
- Fix: Redefine conversion action if needed
Is the tag firing on the right page?
- Check: Tag Assistant on conversion page
- Fix: Move tag to correct page (thank you page)
Are conversions being counted correctly?
- Check: "Every" vs "One" counting method
- Fix: Change to "One" for purchases, "Every" for page views
Is attribution window appropriate?
- Check: 30-day click, 1-day view (default)
- Fix: Extend for longer sales cycles
Debugging Tools
Google Tag Assistant
Installation & Use:
1. Install Chrome extension
2. Navigate to any page on your site
3. Click extension icon
4. View tag status:
- Green = Working correctly
- Yellow = Minor issues
- Red = Critical errors
Tag Assistant Connect Mode:
1. Enable "Connect"
2. Perform actions on site
3. View recorded events
4. Check data being sent
5. Validate conversion fires
Google Ads Diagnostics
Conversion Tracking Status:
Google Ads > Tools > Conversions
Check status indicators:
- "Recording conversions" = Active
- "Unverified" = Tag not detected
- "No recent conversions" = Tag working but no conversions
Tag Installation Test:
1. Tools > Conversions
2. Select conversion action
3. Click "Tag setup" > "Install the tag yourself"
4. Click "Test your tag"
5. Visit conversion page in new tab
6. Verify "Tag is working" message
Chrome DevTools Network Analysis
Request Inspection:
1. F12 > Network tab
2. Filter: "collect" or "google"
3. Trigger conversion
4. Find request to google-analytics.com/collect
5. Check payload includes:
- tid=AW-123456789 (tracking ID)
- ec=conversion (event category)
- ea=conversion_label (event action)
- ev=value (event value)
- cu=currency (currency code)
GTM Preview Mode
For GTM Implementations:
1. Google Tag Manager > Preview
2. Enter your website URL
3. Perform actions
4. Check:
- Tags firing on correct triggers
- Data layer variables populated
- Google Ads conversion tag fires
- No errors in debug panel
GA4 DebugView
For GA4-Linked Conversions:
1. Google Analytics 4 > Configure > DebugView
2. Enable debug mode:
gtag('config', 'G-XXXXXXXXXX', {debug_mode: true});
3. View real-time events
4. Check conversion events
5. Validate parameters
Monitoring & Alerts
Automated Monitoring Setup
1. Conversion Volume Alerts
// Daily check for conversion drops
function checkConversionDrop() {
const today = getConversions('today');
const yesterday = getConversions('yesterday');
const lastWeek = getConversions('last_7_days') / 7;
const dropFromYesterday = (yesterday - today) / yesterday;
const dropFromAverage = (lastWeek - today) / lastWeek;
if (dropFromYesterday > 0.5 || dropFromAverage > 0.3) {
sendAlert({
type: 'Conversion Volume Drop',
today: today,
yesterday: yesterday,
average: lastWeek,
dropPercent: Math.max(dropFromYesterday, dropFromAverage) * 100
});
}
}
2. Tag Health Monitoring
// Check if tags are loading correctly
function monitorTagHealth() {
const checks = {
gtagLoaded: typeof gtag !== 'undefined',
dataLayerExists: typeof window.dataLayer !== 'undefined',
googleAdsTagPresent: !!document.querySelector('script[src*="googletagmanager.com/gtag"]'),
recentErrors: window.dataLayer?.filter(item =>
item[0] === 'error'
).length || 0
};
const issues = Object.entries(checks)
.filter(([key, value]) => !value || value > 0)
.map(([key, value]) => ({ check: key, status: value }));
if (issues.length > 0) {
console.error('Tag Health Issues:', issues);
sendAlert({ type: 'Tag Health', issues });
}
return checks;
}
// Run on every page load
monitorTagHealth();
3. Enhanced Conversion Match Quality
Setup in Google Ads:
1. Tools > Conversions
2. Select conversion action
3. Check "Match quality" metric
4. Set alerts for drops below "Average"
Performance Benchmarks
| Metric | Target | Warning | Critical |
|---|---|---|---|
| Tag Load Time | under 1s | under 3s | over 5s |
| Conversion Latency | under 3 hours | under 24 hours | over 48 hours |
| Match Quality | High | Average | Low |
| Tag Fire Rate | 99%+ | over 95% | under 95% |
| GCLID Capture Rate | 99%+ | over 95% | under 90% |
Best Practices
Implementation Checklist
- Global site tag on all pages
- Conversion event tag only on conversion pages
- Transaction IDs for deduplication
- Currency and value tracking correctly
- Enhanced conversions enabled
- Auto-tagging enabled in Google Ads
- GCLID preservation implemented
- Consent mode configured (if EU traffic)
- Conversion window appropriate for business
- Attribution model reviewed
- Tag Assistant shows no errors
- Conversions verified in Google Ads
- Team trained on troubleshooting
Code Examples
Complete Conversion Tracking Setup:
<!-- Global site tag (gtag.js) - Google Ads -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-123456789"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
// Configure account
gtag('config', 'AW-123456789');
// Enhanced conversions (if applicable)
gtag('set', 'user_data', {
"email": "customer@example.com",
"phone_number": "+12345678900",
"address": {
"first_name": "John",
"last_name": "Doe",
"city": "New York",
"region": "NY",
"postal_code": "10001",
"country": "US"
}
});
</script>
<!-- Conversion Event Tag (on thank-you page only) -->
<script>
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEfGhIjKlMnOp',
'value': 99.99,
'currency': 'USD',
'transaction_id': 'ORDER_12345'
});
</script>
Dynamic Value Tracking:
<script>
// Get order value from page
const orderValue = parseFloat(document.getElementById('order-total').innerText);
const orderId = document.getElementById('order-id').innerText;
// Track conversion with dynamic value
gtag('event', 'conversion', {
'send_to': 'AW-123456789/AbCdEfGhIjKlMnOp',
'value': orderValue,
'currency': 'USD',
'transaction_id': orderId
});
</script>