How to integrate Google Ad Spend data with Mixpanel Using Google Cloud Functions

In this guide, we’ll walk through how to build an automated integration using Google Cloud Functions, the Google Ads API, and the Mixpanel Import API.

Once set up, this pipeline will:

  • Run every morning at 8 AM UTC
  • Fetch yesterday’s Google Ads campaign metrics
  • Transform them into Mixpanel events
  • Import them into your Mixpanel project

Note:
If you manage multiple Google Ads MCC accounts, you’ll create one Cloud Function per account.
The code stays the same; only these values differ:

  • Google Ads Developer Token
  • Google Ads Customer ID

Overview of the Architecture

At a high level, the integration works like this:

  1. Google Cloud Function calls the Google Ads API to fetch campaign metrics from yesterday.
  2. The function transforms each campaign row into a Mixpanel "Ad Data" event.
  3. It sends these events to Mixpanel using the server-side import API.
  4. Cloud Scheduler triggers the function once a day at 8 AM UTC.

Everything is serverless and fully managed.

Step 1: Create OAuth Credentials

First, we need OAuth credentials so the function can access the Google Ads API.

  1. In your Google Cloud project, go to APIs & Services → Credentials.
  2. Click Create credentials → OAuth client ID.
  3. For Application type, select Web application.
  4. Under Authorized redirect URIs, add:
    https://developers.google.com/oauthplayground
    (This is only needed to generate a refresh token; you can remove it later.)
  5. Click Create.
  6. Copy the Client ID and Client Secret — you’ll need them in the next step.

Step 2: Enable the Google Ads API

Next, allow your project to call the Google Ads API.

  1. Go to APIs & Services → Enabled APIs & services.
  2. Click Enable APIs and services.
  3. Search for Google Ads API.
  4. Click it, then press Enable.

Step 3: Generate a Refresh Token

We’ll use Google OAuth Playground to generate a refresh token for your OAuth client.

  1. Go to Google OAuth Playground.
  2. Click the Settings (⚙️) icon in the top-right.
  3. Set OAuth flow to Server-side.
  4. For Access type, select Offline
    → This ensures you receive a refresh token, not just a short-lived access token.
  5. Check Use your own OAuth credentials.
  6. Enter the Client ID and Client Secret from Step 1.
  7. On the left side, find and select Google Ads API scopes.
  8. Click Authorize APIs.
  9. When prompted, sign in with the Google account that has access to your Google Ads account.
  10. Approve the request to manage your Google Ads campaigns.
  11. Once you get an authorization code, click Exchange authorization code for tokens.
  12. Copy the Refresh token — the Cloud Function will use this to access the Google Ads API.

Step 4: Create the Google Cloud Function

Now that we have all required credentials, we can set up the Cloud Function that fetches Google Ads data and sends it to Mixpanel.

4a) Function Configuration

  1. Go to Cloud Functions in your Google Cloud project.
  2. Click Create function → Write a function.

Use the following settings:

  • Service name: mixpanelgoogleads
  • Function name: e.g. mixpanel-google-ads-importer
  • Region: Choose the region closest to you
  • Runtime: Node.js 22
  • Authentication: Allow public access (for simplicity) In production, you’ll typically protect this with IAM + OIDC instead.
  • Billing: Request-based (pay-as-you-go)
  • Autoscaling: Enabled
  • Ingress: All
  • Execution environment: Under Containers → Execution environment, select 2nd gen

4b) Add Dependencies (package.json)

In the inline editor:

  1. Select package.json from the left navigation.
  2. Delete the default content.
  3. Paste:
{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0",
    "mixpanel": "^0.17.0",
    "google-ads-api": "^13.0.0"
  }
}

4c) Add the Function Code (index.js)

  1. Select index.js from the file tree.
  2. Delete the default content.
  3. Paste the following code:
const functions = require('@google-cloud/functions-framework');
const { GoogleAdsApi } = require('google-ads-api');
const Mixpanel = require('mixpanel');

// Configuration:
// It's recommended to pass these values through Environment Variables
// and/or Secret Manager in production.

const MIXPANEL_TOKEN = 'MIXPANEL TOKEN';
const MIXPANEL_SECRET = 'MIXPANEL SECRET';
// For US Data Residency (default):
const MIXPANEL_HOST = 'api.mixpanel.com';
// For EU Data Residency:
// const MIXPANEL_HOST = 'api-eu.mixpanel.com';
// For India Data Residency:
// const MIXPANEL_HOST = 'api-in.mixpanel.com';

const GOOGLE_CLIENT_ID = 'GOOGLE CREDENTIAL CLIENT ID';
const GOOGLE_CLIENT_SECRET = 'GOOGLE CREDENTIAL CLIENT SECRET';
const GOOGLE_CLIENT_REFRESH_TOKEN = 'REFRESH TOKEN FOR YOUR GOOGLE CREDENTIAL';
const GOOGLE_ADS_DEVELOPER_TOKEN = 'GOOGLE ADS DEVELOPER TOKEN';
const GOOGLE_ADS_CUSTOMER_ID = 'GOOGLE CUSTOMER CLIENT ID WITHOUT HYPHENS'; // ex. 1234567890

// End of Configuration

const mixpanel = Mixpanel.init(MIXPANEL_TOKEN, {
  host: MIXPANEL_HOST,
  secret: MIXPANEL_SECRET
});

const client = new GoogleAdsApi({
  client_id: GOOGLE_CLIENT_ID,
  client_secret: GOOGLE_CLIENT_SECRET,
  developer_token: GOOGLE_ADS_DEVELOPER_TOKEN
});

/**
 * Gets campaign data from Google Ads.
 */
function fetchGoogleAdsCampaigns() {
  const customer = client.Customer({
    customer_id: GOOGLE_ADS_CUSTOMER_ID,
    refresh_token: GOOGLE_CLIENT_REFRESH_TOKEN
  });

  // Find metrics for all Google Ads campaigns that ran yesterday
  return customer.query(`
    SELECT
      segments.date,
      campaign.id,
      campaign.name,
      metrics.cost_micros,
      metrics.clicks,
      metrics.impressions
    FROM
      campaign
    WHERE
      metrics.cost_micros > 0
    AND
      segments.date DURING YESTERDAY
  `);
}

/**
 * Turns a Google Ads campaign result into a Mixpanel event.
 */
function transformCampaignToEvent(campaign) {
  return {
    event: 'Ad Data',
    properties: {
      $insert_id: `G-${campaign.segments.date}-${campaign.campaign.id}`,
      // We need to turn the date into a Unix timestamp
      time: new Date(campaign.segments.date).getTime(),
      source: 'Google',
      campaign_id: campaign.campaign.id,

      // metadata about the campaign; matches client-side events
      utm_source: 'google',
      utm_campaign: campaign.campaign.name,

      // Google's cost metric is 1 millionth of the fundamental currency
      cost: campaign.metrics.cost_micros / 1_000_000,
      impressions: campaign.metrics.impressions,
      clicks: campaign.metrics.clicks
    }
  };
}

/**
 * Our function's handler.
 */
functions.http('handler', async (req, res) => {
  try {
    // Get the raw campaign metrics
    const campaigns = await fetchGoogleAdsCampaigns();

    // Transform our raw metrics into Mixpanel events
    const events = campaigns.map(transformCampaignToEvent);

    // Send them to Mixpanel
    mixpanel.import_batch(events, (err) => {
      if (err) {
        throw err;
      }

      res.status(200).send(`Imported ${events.length} events.`);
    });
  } catch (err) {
    res.status(500).send(err);
  }
});

Set the Entry point to:

handler

Before pressing Deploy, replace all placeholder strings (tokens, IDs, secrets) with your actual credentials.

After deployment, copy the trigger URL from the Function details page — you’ll use this when scheduling.

At this point, your function is ready. When triggered, it will:

  1. Query Google Ads for yesterday’s campaign performance.
  2. Convert each row into a Mixpanel "Ad Data" event.
  3. Import all events into your Mixpanel project.

Step 5: Schedule the Function to Run Daily

To keep your Mixpanel data fresh, you’ll want this function to run automatically once a day.

We’ll use Google Cloud Scheduler to trigger the Cloud Function every morning at 8 AM UTC.

  1. Go to Cloud Scheduler in your project
    (or visit: https://console.cloud.google.com/cloudscheduler)
  2. Enable the Cloud Scheduler API if prompted.
  3. Click Schedule a job.

Job Details

  • Name: e.g. gcf-mixpanel-ads-google-daily
  • Region: Same region as your Cloud Function
  • Frequency: 0 8 * * * This cron expression runs the job every day at 8:00 AM.
  • Timezone:
    Select Coordinated Universal Time (UTC), or your preferred timezone.

Click Continue.

Execution Configuration

  • Target type: HTTP
  • URL: Paste the Cloud Function trigger URL you saved earlier.
  • HTTP method: GET
  • Auth header: Select Add OIDC token
  • Service account: Choose a service account with permission to invoke the Cloud Function
    (i.e. it has the Cloud Functions Invoker role).

Click Create.

Your scheduled job is now live.


Thats it!! Google Ads → Mixpanel Sync Is Automated

Your setup is now complete:

  • Every morning at 8 AM UTC, Cloud Scheduler triggers your Cloud Function.
  • The function calls the Google Ads API to fetch the previous day’s campaign metrics.
  • It transforms them into Mixpanel "Ad Data" events and imports them using the Mixpanel Import API.
  • Mixpanel now has daily, campaign-level Google Ads data you can join with in-product events.

This integration gives you a single place to analyze:

  • Spend, clicks, impressions
  • CPC, CPM, CTR
  • Campaign performance tied to signups, activations, and conversions

Integrating Google Ads with Mixpanel through a scheduled Google Cloud Function gives you a fully automated, reliable way to bring campaign performance into your analytics stack. By pulling daily spend, impressions, and click data directly from the Google Ads API and importing it into Mixpanel, you unlock the ability to analyze marketing performance alongside in-product behavior — without manual exports or spreadsheets.

Need help with Mixpanel Ad Spend Integration?  Email us at support@optizent.com or fill out the contact us form.