> ## Documentation Index
> Fetch the complete documentation index at: https://docs.masivo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Ads integration

> Track and send conversion data from Masivo to Google Ads

## What you can sync

* **Purchase conversions**: Track completed purchases as conversions in Google Ads
* **Event conversions**: Track custom events (sign-ups, leads, etc.) as conversions
* **Conversion values**: Send transaction amounts to measure ROAS (Return on Ad Spend)
* **Order IDs**: Link purchases to specific transactions for better tracking

<Info>
  Looking for **audience / Customer Match** sync? That is a separate destination:
  [Google Ads Remarketing](/guides/CDP/integrations/google-ads-remarketing/overview).
  Remarketing uses the Data Manager API and does **not** require a developer
  token.
</Info>

## Prerequisites

Before setting up the integration, you'll need:

* A Google Ads account with active campaigns
* Google Ads API access (requires approval from Google)
* A Conversion Action created in Google Ads
* OAuth 2.0 credentials from Google Cloud Console

<Info>
  Getting API access requires applying through the [Google Ads API
  Center](https://ads.google.com/aw/apicenter). Basic access is typically
  approved within 24 hours for accounts with a billing history.
</Info>

## Getting your credentials

### 1. Customer ID

Your Google Ads Customer ID is the 10-digit account number:

1. Log in to [Google Ads](https://ads.google.com)
2. Look for the account number at the top of the page (format: `123-456-7890`)
3. Enter in Masivo with or without dashes (e.g., `123-456-7890` or `1234567890`)

<Info>
  Masivo automatically removes dashes from Customer IDs, so you can enter them
  in either format.
</Info>

### 2. Developer Token

Request API access from Google Ads:

1. Go to **Tools & Settings → API Center** in Google Ads
2. Click **Apply for access**
3. Fill out the application form
4. Once approved, copy your **Developer Token**

<Warning>
  Developer tokens are sensitive credentials. Never share them publicly or
  commit them to version control.
</Warning>

### 3. OAuth Credentials

Create OAuth 2.0 credentials in Google Cloud Console:

1. Go to [Google Cloud Console](https://console.cloud.google.com)
2. Create a new project or select an existing one
3. Enable the **Google Ads API**
4. Go to **APIs & Services → Credentials**
5. Click **Create Credentials → OAuth client ID**
6. Choose **Web application** as application type
7. Add authorized redirect URIs (e.g., `http://localhost:3000/oauth2callback`)
8. Save and copy your **Client ID** and **Client Secret**

### 4. Refresh Token

Generate a refresh token using OAuth 2.0 flow:

1. Use Google's OAuth 2.0 Playground or implement the OAuth flow
2. Request scopes: `https://www.googleapis.com/auth/adwords`
3. Complete the authorization flow
4. Exchange the authorization code for tokens
5. Copy the **Refresh Token** (it won't expire unless revoked)

<Tip>
  You can use the [OAuth 2.0
  Playground](https://developers.google.com/oauthplayground) to quickly generate
  a refresh token. Just configure it with your Client ID and Client Secret.
</Tip>

### 5. Conversion Action ID

Create a conversion action in Google Ads:

1. Go to **Tools & Settings → Conversions** in Google Ads
2. Click **+ New conversion action**
3. Choose **Import** → **Other data sources**
4. Select **Track conversions from clicks**
5. Configure your conversion settings:
   * **Category**: Purchase, Sign-up, Lead, etc.
   * **Value**: Use different values for each conversion
   * **Count**: Every conversion (for purchases) or One (for sign-ups)
   * **Click-through conversion window**: 30-90 days recommended
   * **Attribution model**: Choose based on your business
6. Save and copy the **Conversion Action ID** (visible in the conversion details URL or settings)

## Configuration

Once you have all credentials:

1. Go to **Settings → Integrations → Google Ads** in the Masivo dashboard
2. Enter your credentials:
   * **Customer ID**: Your 10-digit account number (with or without dashes)
   * **Developer Token**: From Google Ads API Center
   * **Client ID**: From Google Cloud Console
   * **Client Secret**: From Google Cloud Console
   * **Refresh Token**: Generated via OAuth flow
   * **Conversion Action ID**: From your conversion action
3. Enable the features you want to sync:
   * **Events**: Track custom event conversions
   * **Purchases**: Track completed purchase conversions
4. Click **Save** to activate the integration

## How it works

Google Ads conversion tracking works by connecting ad clicks to conversions on your site or app:

### 1. Click tracking

When a user clicks your Google Ad, Google automatically adds tracking parameters to the landing URL:

* **gclid** (Google Click ID): Used for web traffic
* **gbraid** (Google Bounce Rate Analysis ID): Used for iOS 14.5+ traffic
* **wbraid** (Web to App Bounce Rate Analysis ID): Used for web-to-app conversions

### 2. Capturing click identifiers

Your website or app must capture these parameters:

```javascript theme={null}
// Example: Capture gclid from URL
const urlParams = new URLSearchParams(window.location.search);
const gclid = urlParams.get("gclid");
const gbraid = urlParams.get("gbraid");
const wbraid = urlParams.get("wbraid");

// Store for later use (localStorage, cookie, or session)
if (gclid) localStorage.setItem("gclid", gclid);
if (gbraid) localStorage.setItem("gbraid", gbraid);
if (wbraid) localStorage.setItem("wbraid", wbraid);
```

<Warning>
  These identifiers are **required** for conversion tracking. Without them,
  Masivo cannot attribute conversions to your Google Ads campaigns.
</Warning>

### 3. Sending conversions

When a conversion happens (purchase, sign-up, etc.), send the event to Masivo **with** the stored click identifier:

```json theme={null}
{
  "type": "PURCHASE",
  "customer_id": "cust_123",
  "gclid": "EAIaIQobChMI0tXXyPaE8wIVjRmtBh3XqAZ7EAAYASAAEgJqxfD_BwE",
  "order": {
    "purchase_id": "ORD-789",
    "value": 159.99,
    "discounted_value": 149.99
  },
  "currency": "USD",
  "issued_at": "2025-10-20T14:30:00Z"
}
```

### 4. Automatic sync

Masivo automatically:

* Validates the event and configuration
* Transforms the data to Google Ads format
* Sends the conversion to Google Ads API
* Handles errors and retries if needed

## Data structure

### Purchase conversion

```json theme={null}
{
  "type": "PURCHASE",
  "customer_id": "cust_123",
  "brand_id": "0001",
  "gclid": "EAIaIQobChMI0tXXyPaE8wIVjRmtBh3XqAZ7EAAYASAAEgJqxfD_BwE",
  "order": {
    "purchase_id": "ORD-789",
    "value": 159.99,
    "discounted_value": 149.99,
    "payment_method": "CREDIT",
    "products": [
      {
        "sku": "PROD-001",
        "value": 79.99,
        "amount": 2
      }
    ]
  },
  "currency": "USD",
  "fulfilled": true,
  "issued_at": "2025-10-20T14:30:00Z",
  "fulfilled_at": "2025-10-20T14:30:00Z"
}
```

### Event conversion

```json theme={null}
{
  "type": "EVENT",
  "customer_id": "cust_123",
  "brand_id": "0001",
  "gclid": "EAIaIQobChMI0tXXyPaE8wIVjRmtBh3XqAZ7EAAYASAAEgJqxfD_BwE",
  "event_name": "lead_signup",
  "value": 25.0,
  "currency": "USD",
  "issued_at": "2025-10-20T14:30:00Z"
}
```

### iOS conversion (using gbraid)

For iOS 14.5+ users where gclid is not available:

```json theme={null}
{
  "type": "PURCHASE",
  "customer_id": "cust_123",
  "gbraid": "0AAAAAo4mICNBGfEXAMPLEExampleGbraidString",
  "order": {
    "purchase_id": "ORD-790",
    "value": 99.99
  },
  "currency": "USD",
  "issued_at": "2025-10-20T14:30:00Z"
}
```

## Required fields

### For all conversions

| Field                           | Type   | Description                             |
| ------------------------------- | ------ | --------------------------------------- |
| `type`                          | string | Either `PURCHASE` or `EVENT`            |
| `customer_id`                   | string | Unique customer identifier              |
| `gclid` OR `gbraid` OR `wbraid` | string | **Required**: Click identifier from ad  |
| `issued_at`                     | string | ISO 8601 timestamp of the conversion    |
| `currency`                      | string | ISO 4217 currency code (default: `USD`) |

### For purchases

| Field                    | Type   | Description                      |
| ------------------------ | ------ | -------------------------------- |
| `order.value`            | number | Total order value                |
| `order.purchase_id`      | string | Unique order identifier          |
| `order.discounted_value` | number | Value after discounts (optional) |

### For events

| Field        | Type   | Description                             |
| ------------ | ------ | --------------------------------------- |
| `value`      | number | Conversion value (for lead value, etc.) |
| `event_name` | string | Name of the custom event (optional)     |

## Understanding click identifiers

### GCLID (Google Click ID)

* **Format**: Long alphanumeric string (e.g., `EAIaIQobChMI0tXXyPaE8wIVjRmtBh3XqAZ7EAAYASAAEgJqxfD_BwE`)
* **Usage**: Standard web tracking
* **Platform**: All web browsers
* **Expiration**: Valid for 90 days after click
* **Priority**: Use gclid if available

### GBRAID (Google Bounce Rate Analysis ID)

* **Format**: Alphanumeric string starting with specific prefix
* **Usage**: iOS 14.5+ tracking without cookies
* **Platform**: Safari on iOS/iPadOS
* **Expiration**: Valid for click-through conversion window
* **Priority**: Use when gclid is not available (iOS)

### WBRAID (Web to App Bounce Rate Analysis ID)

* **Format**: Alphanumeric string
* **Usage**: Web-to-app conversion tracking
* **Platform**: Mobile apps (iOS/Android)
* **Expiration**: Valid for click-through conversion window
* **Priority**: Use when tracking web clicks that convert in-app

<Info>
  **Priority order**: Always use `gclid` if available. Only use `gbraid` or
  `wbraid` when `gclid` is not present. Never use multiple identifiers in the
  same conversion.
</Info>

## Conversion value logic

Masivo automatically determines the conversion value based on event type:

### For PURCHASE events

```javascript theme={null}
// Uses order.value or order.discounted_value
conversionValue = order.value || order.discounted_value || 0;
```

### For EVENT events

```javascript theme={null}
// Uses the event value directly
conversionValue = data.value || 0;
```

## Validation

Before sending conversions to Google Ads, Masivo validates:

### Configuration validation

* ✅ Customer ID is exactly 10 digits (dashes are automatically removed if present)
* ✅ Developer token is provided
* ✅ OAuth credentials (client\_id, client\_secret, refresh\_token) are complete
* ✅ Conversion Action ID is configured

### Message validation

* ✅ Event type is enabled (events or purchases)
* ✅ At least one click identifier (gclid, gbraid, or wbraid) is present
* ✅ Customer ID exists
* ✅ Timestamp is in valid ISO 8601 format
* ✅ For purchases: order object with value exists

<Warning>
  If any required field is missing, the conversion will be **skipped** and
  logged. Check your event payload to ensure all required fields are included.
</Warning>

## Best practices

### 1. Always capture click identifiers

Implement tracking on every landing page:

```javascript theme={null}
// Capture and persist on page load
const captureClickId = () => {
  const params = new URLSearchParams(window.location.search);
  const gclid = params.get("gclid");
  const gbraid = params.get("gbraid");
  const wbraid = params.get("wbraid");

  if (gclid) {
    localStorage.setItem("gclid", gclid);
    // Set expiration (90 days)
    localStorage.setItem(
      "gclid_expires",
      Date.now() + 90 * 24 * 60 * 60 * 1000
    );
  }
  if (gbraid) localStorage.setItem("gbraid", gbraid);
  if (wbraid) localStorage.setItem("wbraid", wbraid);
};

captureClickId();
```

### 2. Check expiration before sending

```javascript theme={null}
const getValidGclid = () => {
  const gclid = localStorage.getItem("gclid");
  const expires = localStorage.getItem("gclid_expires");

  if (gclid && expires && Date.now() < parseInt(expires)) {
    return gclid;
  }

  return null;
};
```

### 3. Send conversions immediately

Track conversions as soon as they happen:

```javascript theme={null}
// After successful purchase
const trackPurchase = async orderData => {
  const gclid = getValidGclid();

  await fetch("/api/events/track", {
    method: "POST",
    body: JSON.stringify({
      type: "PURCHASE",
      customer_id: user.id,
      gclid: gclid, // Include if available
      order: orderData,
      currency: "USD",
      issued_at: new Date().toISOString()
    })
  });
};
```

### 4. Use accurate conversion values

* For purchases: Use the actual charged amount (after discounts)
* For events: Use realistic value estimates (e.g., average lead value)
* Always include currency code

### 5. Set up conversion tracking early

The more conversion data Google Ads has, the better its automated bidding:

* Start tracking from day one
* Track multiple conversion types (purchases, sign-ups, leads)
* Be consistent with value attribution

### 6. Monitor conversion import status

Check your Google Ads account regularly:

1. Go to **Tools & Settings → Conversions**
2. Select your conversion action
3. Check the **Status** column for import errors
4. Review conversion counts match your expectations

## Limitations

* **Click identifiers are required**: Conversions without gclid/gbraid/wbraid will be skipped
* **90-day attribution window**: gclid values expire after 90 days (or your configured window)
* **Real identifiers only**: Cannot use mock or fabricated click identifiers
* **API rate limits**: Subject to Google Ads API rate limits (typically not an issue)
* **Approval required**: Requires approved Google Ads API access

<Warning>
  Google validates all click identifiers cryptographically. Fabricated or
  expired identifiers will be rejected with a validation error.
</Warning>

## Troubleshooting

### Conversions not showing in Google Ads

**Check click identifier capture:**

```javascript theme={null}
// Debug: Log captured values
console.log("gclid:", localStorage.getItem("gclid"));
console.log("gbraid:", localStorage.getItem("gbraid"));
```

**Verify integration is enabled:**

* Settings → Integrations → Google Ads
* Ensure "Purchases" or "Events" toggle is ON

**Check customer ID format:**

* Must be 10 digits (with or without dashes)
* Example: `8623528631` ✅
* Example: `862-352-8631` ✅ (dashes are automatically removed)

### "Invalid gclid" errors

* **Cause**: Expired, modified, or fabricated gclid
* **Solution**: Ensure you're capturing the gclid directly from the URL without modification
* **Note**: gclid values are cryptographically signed and validated by Google

### "Configuration incomplete" errors

Check that all credentials are configured:

```bash theme={null}
✅ Customer ID (10 digits, with or without dashes)
✅ Developer Token
✅ Client ID
✅ Client Secret
✅ Refresh Token
✅ Conversion Action ID
```

### "Conversion action not found" errors

* Verify the Conversion Action ID is correct
* Ensure the conversion action is active in Google Ads
* Check that it's configured for "clicks" (not "views")

### "Authentication failed" errors

* **Refresh token expired**: Regenerate your refresh token via OAuth flow
* **Invalid credentials**: Double-check client\_id and client\_secret
* **API access revoked**: Verify your API access status in Google Ads

### Conversions delayed or not appearing

* **Normal delay**: Google Ads can take 3-9 hours to process imported conversions
* **Check import history**: Tools & Settings → Conversions → Import history
* **Verify timestamps**: Ensure `issued_at` is accurate and recent

## Testing your integration

### 1. Create a test conversion action

Set up a separate conversion action for testing:

1. Go to Google Ads → Tools & Settings → Conversions
2. Create a new conversion action with "Test" in the name
3. Use a low value to identify test conversions
4. Use this Conversion Action ID in your test environment

### 2. Generate a real gclid

You cannot fabricate valid gclid values. To test:

1. Create a test campaign in Google Ads
2. Click your own ad from a real browser
3. Capture the gclid from the landing page URL
4. Use this gclid in your test conversion (valid for 90 days)

### 3. Use validation mode

Temporarily enable validation in development:

```typescript theme={null}
// In your codebase (for testing only)
const p = {
  conversions: [conversion],
  partial_failure: true,
  validate_only: true, // Test without recording conversion
  customer_id: cleanCustomerId
};
```

<Tip>
  With `validate_only: true`, Google Ads validates your conversion data without
  recording it. This is useful for testing configuration and data format.
</Tip>

### 4. Monitor the response

Check Masivo logs for integration status:

```json theme={null}
// Success response
{
  "processedCount": 1,
  "errorCount": 0
}

// Error response
{
  "error": "The imported gclid could not be decoded...",
  "details": "conversions[0].gclid"
}
```

## Common integration patterns

### E-commerce checkout

```javascript theme={null}
// 1. Capture gclid on landing
useEffect(() => {
  const params = new URLSearchParams(window.location.search);
  const gclid = params.get("gclid");
  if (gclid) sessionStorage.setItem("gclid", gclid);
}, []);

// 2. Send conversion after purchase
const handlePurchaseComplete = async order => {
  const gclid = sessionStorage.getItem("gclid");

  await trackEvent({
    type: "PURCHASE",
    customer_id: user.id,
    gclid: gclid,
    order: {
      purchase_id: order.id,
      value: order.total,
      discounted_value: order.discountedTotal
    },
    currency: "USD",
    issued_at: new Date().toISOString()
  });
};
```

### Lead generation

```javascript theme={null}
// After form submission
const handleFormSubmit = async formData => {
  const gclid = localStorage.getItem("gclid");

  await trackEvent({
    type: "EVENT",
    customer_id: formData.email,
    gclid: gclid,
    event_name: "lead_form_submission",
    value: 50.0, // Estimated lead value
    currency: "USD",
    issued_at: new Date().toISOString()
  });
};
```

### Mobile app (with gbraid)

```javascript theme={null}
// React Native or Expo
import { useURL } from "expo-linking";

const captureClickIds = () => {
  const url = useURL();

  if (url) {
    const params = new URL(url).searchParams;
    const gbraid = params.get("gbraid");

    if (gbraid) {
      AsyncStorage.setItem("gbraid", gbraid);
    }
  }
};
```

## Next steps

After setting up the integration:

1. **Test thoroughly**: Verify conversions appear in Google Ads (allow 3-9 hours)
2. **Enable automated bidding**: Use conversion data for Smart Bidding strategies
3. **Set up value-based bidding**: Optimize for conversion value, not just count
4. **Track multiple actions**: Set up different conversion actions for different goals
5. **Monitor performance**: Check conversion import status regularly

<Info>
  Need help? Check our [API Reference](/api-reference/events/create) for more
  details on sending events to Masivo, or contact support for integration
  assistance.
</Info>
