Skip to main content

Advertising Platform Integration

Integrate GA4 with major advertising platforms (Google Ads, Meta, LinkedIn, Microsoft) for unified measurement and optimization.

Platform Overview

Integration Methods

| Platform | Native GA4 | Server-Side | API Import | |----------|------------|-------------|------------| | Google Ads | Yes (linked) | Yes | Yes | | Meta Ads | No | Yes (CAPI) | Yes | | LinkedIn Ads | No | Yes | Yes | | Microsoft Ads | No | Yes | Yes | | TikTok Ads | No | Yes | Yes |

Why Integrate?

| Benefit | Description | |---------|-------------| | Cross-platform attribution | Unified view across channels | | Audience sharing | Use GA4 segments for targeting | | Offline conversion import | Report CRM conversions to ad platforms | | Better optimization | Platform algorithms use your data |

Google Ads Integration

Linking GA4 to Google Ads

  1. GA4 AdminProduct LinksGoogle Ads links
  2. Click Link
  3. Select Google Ads account
  4. Enable Personalized advertising and Auto-tagging

Auto-Tagging Benefits

When enabled, Google Ads appends gclid to URLs:

https://yoursite.com/landing-page?gclid=abc123xyz

This enables:

  • Automatic campaign data in GA4
  • Cross-device attribution
  • Offline conversion import
  • Better bidding signals

Import GA4 Conversions to Google Ads

  1. GA4 AdminProduct LinksGoogle Ads links
  2. Click on linked account
  3. Select Import tab
  4. Choose conversion events to import

Best practice: Import both primary (purchase) and micro (add_to_cart) conversions.

Enhanced Conversions for Leads

For lead gen, use enhanced conversions with server-side:

// In server-side GTM
const conversionData = {
  conversionAction: 'AW-CONVERSION_ID/LABEL',
  conversionDateTime: new Date().toISOString(),
  userIdentifiers: [{
    hashedEmail: sha256(event.user_data.email.toLowerCase()),
    hashedPhoneNumber: sha256(normalizePhone(event.user_data.phone))
  }]
};

Meta Ads Integration

Conversions API (CAPI)

Server-side is essential for Meta attribution accuracy:

Browser          Server             Meta
   │                │                 │
   │  Pixel Event   │                 │
   │────────────────│─────────────────│
   │                │                 │
   │    Blocked?    │   Server Event  │
   │       ⚠        │────────────────▶│
   │                │                 │
   └────────────────┴─────────────────┘

Server-Side GTM Setup

  1. Install Meta CAPI tag template
  2. Configure:

| Field | Value | |-------|-------| | Pixel ID | Your 15-16 digit ID | | Access Token | System user token | | Event Name | From client | | User Data | Map from event |

Event Deduplication

Use the same event_id in both browser pixel and CAPI:

// Generate unique event ID
const eventId = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

// Browser pixel
fbq('track', 'Purchase', {
  value: 99.99,
  currency: 'USD'
}, { eventID: eventId });

// Data layer for server-side
dataLayer.push({
  event: 'purchase',
  event_id: eventId,  // Same ID
  value: 99.99,
  currency: 'USD'
});

GA4 + Meta Attribution

Compare in BigQuery:

-- Compare GA4 vs Meta attribution
WITH ga4_purchases AS (
  SELECT
    user_pseudo_id,
    traffic_source.source,
    (SELECT value.double_value FROM UNNEST(event_params) WHERE key = 'value') as revenue
  FROM `project.analytics.events_*`
  WHERE event_name = 'purchase'
    AND _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
)
SELECT
  CASE
    WHEN LOWER(source) LIKE '%facebook%' OR LOWER(source) LIKE '%fb%' THEN 'Meta'
    WHEN LOWER(source) LIKE '%google%' THEN 'Google'
    ELSE 'Other'
  END as platform,
  COUNT(*) as purchases,
  SUM(revenue) as total_revenue
FROM ga4_purchases
GROUP BY platform

LinkedIn Ads Integration

Insight Tag Setup

Install via GTM:

// LinkedIn Insight Tag (via GTM Custom HTML)
_linkedin_partner_id = "YOUR_PARTNER_ID";
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(_linkedin_partner_id);

(function(l) {
  if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])};
  window.lintrk.q=[]}
  var s = document.getElementsByTagName("script")[0];
  var b = document.createElement("script");
  b.type = "text/javascript";b.async = true;
  b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
  s.parentNode.insertBefore(b, s);})(window.lintrk);

Conversion Tracking

// Track LinkedIn conversions
dataLayer.push({
  event: 'generate_lead',
  linkedin_conversion_id: 12345678
});

// In GTM, fire LinkedIn conversion pixel:
lintrk('track', { conversion_id: 12345678 });

Server-Side LinkedIn

For B2B with long sales cycles, import offline conversions:

// LinkedIn Conversions API
const linkedinConversion = {
  conversion: 'urn:lla:llaPartnerConversion:123456',
  conversionHappenedAt: Date.now(),
  user: {
    userIds: [{
      idType: 'SHA256_EMAIL',
      idValue: sha256(email)
    }]
  },
  conversionValue: {
    currencyCode: 'USD',
    amount: '50000'
  }
};

await fetch('https://api.linkedin.com/rest/conversionEvents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'LinkedIn-Version': '202401'
  },
  body: JSON.stringify(linkedinConversion)
});

Microsoft Ads Integration

UET Tag Setup

// Microsoft UET Tag
(function(w,d,t,r,u){var f,n,i;w[u]=w[u]||[],f=function(){
var o={ti:"YOUR_TAG_ID"};o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")},
n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function(){
var s=this.readyState;s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)},
i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)
})(window,document,"script","//bat.bing.com/bat.js","uetq");

Conversion Events

// Microsoft Ads conversion
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 99.99,
  'currency': 'USD'
});

Offline Import

Microsoft supports offline conversion import via:

  1. Manual CSV upload
  2. API integration
  3. Google Ads import (mirror your Google setup)

Cross-Platform Attribution

The Attribution Challenge

Each platform claims credit differently:

| Platform | Default Model | Lookback | |----------|---------------|----------| | GA4 | Data-driven | 30-90 days | | Google Ads | Data-driven | 30 days | | Meta | 7-day click / 1-day view | 7/1 days | | LinkedIn | Last touch | 90 days | | Microsoft | Last click | 30 days |

Reconciliation Strategy

  1. Accept discrepancy - Each platform optimizes to its data
  2. Use GA4 for comparison - Cross-channel view
  3. Run incrementality tests - True lift measurement
  4. Focus on trends - Not absolute numbers

Unified Dashboard

Create cross-platform view:

-- BigQuery: Platform performance comparison
SELECT
  CASE
    WHEN REGEXP_CONTAINS(LOWER(source), r'facebook|fb|instagram|ig|meta') THEN 'Meta'
    WHEN REGEXP_CONTAINS(LOWER(source), r'google|cpc') AND medium = 'cpc' THEN 'Google Ads'
    WHEN REGEXP_CONTAINS(LOWER(source), r'linkedin|li') THEN 'LinkedIn'
    WHEN REGEXP_CONTAINS(LOWER(source), r'bing|microsoft') THEN 'Microsoft'
    ELSE 'Other'
  END as platform,
  COUNT(DISTINCT user_pseudo_id) as users,
  COUNT(DISTINCT session_id) as sessions,
  COUNTIF(event_name = 'purchase') as conversions,
  SUM(CASE WHEN event_name = 'purchase' THEN value END) as revenue
FROM (
  SELECT
    user_pseudo_id,
    traffic_source.source as source,
    traffic_source.medium as medium,
    event_name,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') as session_id,
    (SELECT value.double_value FROM UNNEST(event_params) WHERE key = 'value') as value
  FROM `project.analytics.events_*`
  WHERE _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
)
GROUP BY platform
ORDER BY revenue DESC

Audience Sharing

GA4 to Google Ads

Automatic when linked:

  1. Create audience in GA4
  2. Appears in Google Ads shared library
  3. Use for targeting and bidding

GA4 to Meta (via Segment/mParticle)

// Example: Segment to Meta sync
analytics.identify(userId, {
  email: user.email,
  high_value: user.ltv > 500
});

// Segment syncs to Facebook Custom Audiences

Manual Export for All Platforms

-- Export audience for upload
SELECT
  email_hash,
  phone_hash
FROM (
  SELECT
    sha256(LOWER(TRIM(user_data.email))) as email_hash,
    sha256(REGEXP_REPLACE(user_data.phone, r'[^0-9+]', '')) as phone_hash
  FROM `project.analytics.user_data`
  WHERE segment = 'high_value'
)
WHERE email_hash IS NOT NULL

Best Practices

Consistent Naming

| Element | Format | Example | |---------|--------|---------| | Campaign | platform_objective_target | google_awareness_enterprise | | Ad Set | audience_placement | remarketing_feed | | Ad | creative_variant | video_v1 |

Measurement Hierarchy

┌─────────────────────────────────────────────────────────┐
│                 Measurement Strategy                     │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Level 1: Platform Reporting                            │
│  → Daily optimization, in-platform metrics              │
│                                                         │
│  Level 2: GA4 Cross-Platform                            │
│  → Weekly comparison, attribution analysis              │
│                                                         │
│  Level 3: Incrementality Testing                        │
│  → Monthly/quarterly, true lift measurement             │
│                                                         │
└─────────────────────────────────────────────────────────┘

Previous: Email Platform Integration Next: E-commerce Platform Integration