Type something to search...
n8n to Google Ads

Offline Conversions

Google Ads Offline Conversions via n8n

TutorialsIvanUpdated: 23 Apr, 2026

If you are running lead generation campaigns, Offline Conversion Tracking is non-negotiable. It’s the only way to tell Google, “Hey, this lead actually bought something.”

While tools like Zapier or Make have built-in modules for this, n8n currently lacks a native “Upload Offline Conversion” node for Google Ads.

But that doesn’t mean you can’t do it. In fact, doing it manually via the HTTP Request node gives you significantly more control over error handling and data formatting.

In this guide, I’ll walk you through exactly how to build a robust pipeline in n8n using the Google Ads API.

Note

Why choose n8n over Zapier or Make in the first place?


While Zapier and Make have native modules for this, their usage-based pricing gets expensive quickly as your conversion volume grows.


With n8n’s Community Edition, you can self-host the platform, using the 1-click instal app on DigitalOcean and process unlimited events for a flat server fee (often as low as $6/mo).

The Workflow Overview

We are building a simple, linear pipeline that takes a success event (like a Stripe Charge, Adyen Authorization, or CRM Lead Stage update) and pushes it to Google.

(Processing payments through Adyen? Check out our dedicated guide on Adyen to Google Ads Offline Conversions via n8n to handle Adyen’s payload structure and 10-second response rule. Running a Shopify store with Server-Side GTM? See our Shopify Webhook Google Ads Tracking with Stape tutorial and Shopify Webhook Uplift Case Study.)

graph LR
    %% Style Definitions
    classDef trigger fill:#e0e7ff,stroke:#4f46e5,stroke-width:2px
    classDef crypto fill:#fff,stroke:#333,stroke-width:1px
    classDef api fill:#dcfce7,stroke:#16a34a,stroke-width:2px

    A(Trigger<br/>e.g. Stripe / Adyen):::trigger --> B(Crypto<br/>SHA256 Hash):::crypto
    B --> C(Set Variables<br/>Prep Data):::crypto
    C --> D(HTTP Request<br/>Google Ads API):::api

Prerequisites: Getting Your Credentials

Before we open n8n, you need three key pieces of information from Google. This is often the hardest part, so let’s get it out of the way.

1. Developer Token

You need a “Basic Access” developer token to use the API.

  • Go to your Google Ads MCC Account.
  • Navigate to Tools & Settings > Setup > API Center.
  • Fill out the form to request a token. (For internal use, it’s usually approved instantly or within days).

2. Client ID & Client Secret

You need to create a project in Google Cloud Platform (GCP).

  • Go to the Google Cloud Console.
  • Create a new project and enable the Google Ads API.
  • Go to APIs & Services > Credentials and creating an OAuth 2.0 Client ID.
  • Copy your Client ID and Client Secret.

3. Conversion Action ID

  • In Google Ads, go to Goals > Conversions > Summary.
  • Click on the conversion action you want to track (e.g., “Qualified Lead”).
  • Look at the URL in your browser. You will see ctId=123456789. That number is your Conversion Action ID.

Step 1: Hashing the Email (Privacy First)

Google requires “Enhanced Conversions” data to be hashed using SHA-256. You cannot send plain text emails.

  1. Add a Crypto node to your n8n workflow.
  2. Action: Hash.
  3. Algorithm: SHA-256.
  4. Value: Map the user’s email from your trigger node.
  5. Property Name: Set this to sha256_email.

Note: Google expects the email to be lowercase and trimmed of whitespace before hashing. You can use a generic function {{ $json.email.trim().toLowerCase() }} inside the Crypto node value field to ensure this.


Step 2: Preparing the Data

To keep our HTTP request clean, I recommend using a Set (or “Edit Fields”) node to define all our variables in one place.

Create a new node and define the following fields:

  • customer_id: The Google Ads account ID where the conversion belongs (digits only, no dashes).
  • conversion_action_id: The ID you grabbed from the URL earlier.
  • order_id: A unique transaction ID (e.g., Stripe Charge ID). This prevents duplicate reporting.
  • conversion_value: The numeric value of the sale (e.g., 99.00).
  • currency_code: ISO currency code (e.g., USD, EUR).
  • conversion_date: The time the conversion happened.
  • login_customer_id: If you are using an MCC account to authenticate, put your MCC ID here. If you are using a direct account, put the standard account ID.

Step 3: The HTTP Request (The Heavy Lifting)

Now for the magic. We will send a POST request to the Google Ads API.

Authentication

In the n8n HTTP Request node:

  1. Authentication: Predefined Credential Type.
  2. Credential Type: Google Ads OAuth2 API.
  3. Setup: Enter your Client ID, Client Secret, and Developer Token here.

Request Configuration

  • Method: POST

  • URL:

    https://googleads.googleapis.com/v24/customers/{{ $json.customer_id }}:uploadClickConversions

    Notes:

    Use v24 or the latest stable version.

    Replace {{ $json.customer_id }} with your variable.

Headers

You must manually add these headers for the request to work:

  • developer-token: Your API Developer Token (Yes, even if it’s in the credential, adding it here ensures it’s passed correctly in custom calls).
  • login-customer-id: {{ $json.login_customer_id }} (Crucial if you are authenticating via an MCC).

The JSON Body

Select “JSON” as the Body Content type and paste this structure:

{
  "conversions": [
    {
      "orderId": "{{ $json.order_id }}",
      "currencyCode": "{{ $json.currency_code.toUpperCase() }}",
      "conversionValue": {{ $json.conversion_value }},
      "userIdentifiers": [
        {
          "hashedEmail": "{{ $json.sha256_email }}"
        }
      ],
      "conversionAction": "customers/{{ $json.customer_id }}/conversionActions/{{ $json.conversion_action_id }}",
      "conversionDateTime": "{{ DateTime.fromSeconds($json.conversion_date).setZone($json.accountTimezone).toFormat('yyyy-MM-dd HH:mm:ssZZ') }}",
      "consent": {
        "adUserData": "GRANTED",
        "adPersonalization": "GRANTED"
      }
    }
  ],
  "partialFailure": true
}

Step 4: Verifying and Debugging Uploads

Once your workflow runs, how do you verify Google is receiving and attributing your offline conversions?

The 3–6 Hour Processing Delay

Unlike client-side pixel events that show up almost immediately in analytics dashboards, offline conversion uploads via the Google Ads API take 3 to 6 hours (and sometimes up to 24 hours) to process and appear across campaign reports.

Checking Upload Diagnostics

To verify conversion upload health:

  1. In Google Ads, navigate to Goals > Conversions > Uploads.
  2. Open the Upload history tab.
  3. Review the batch status, total conversions received, and error counts.

Because we set "partialFailure": true in the API payload, valid conversions in a batch still succeed even if a single item fails. Common Google Ads API error codes include:

  • CONVERSION_ALREADY_EXISTS: A conversion with this exact orderId has already been recorded. Google automatically deduplicates these.
  • CLICK_NOT_FOUND / EXPIRED: If you pass a gclid, the click must fall within your conversion action’s lookback window. When utilizing Enhanced Conversions for Leads with hashedEmail, Google matches user identifiers directly against signed-in accounts without requiring a click ID.
  • UNPARSEABLE_DATE_TIME: Verify your datetime string matches the required format (yyyy-MM-dd HH:mm:ssZZ).

Next Steps: Connecting Payment Gateways

Now that your core upload pipeline is configured, you can trigger this flow from any backend system: Stripe, HubSpot, Salesforce, or your own database.

If your checkout runs on Adyen, see our step-by-step tutorial on connecting Adyen to Google Ads via n8n, covering Adyen webhook event filtering, the 10-second response acknowledgement, and minor currency unit conversion.

Need this exact workflow?

Struggling to connect your CRM to ad platforms? We build robust marketing data pipelines that just work. Let's automate your tracking.

Book a Discovery Call
Share:

Related Posts

Adyen Purchase TrackingGoogle Ads Offline Conversions

Adyen to Google Ads Offline Conversions via n8n

TutorialsIvanPublished: 08 Oct, 2026

When running paid acquisition campaigns, relying solely on client-side conversion tags (like Google Tag Manager scripts on a checkout confirmation page) leaves costly blind spots. Browser privacy rest

read more
LTV based nCACAdvanced Google Ads bidding strategy

nCAC Google Ads Bidding Strategy based on LTV

TutorialsIvanPublished: 29 Sep, 2026

Your Google Ads account might be pausing your most profitable products right now — and the algorithm thinks it's doing you a favor. Lots of Google Ads managers live and die by immediate, dashboard-re

read more
Google Ads POAS TrackingShopify, Server-Side GTM, Stape & Matrixify

Shopify POAS Tracking for Google Ads via Stape

TutorialsIvanPublished: 23 Aug, 2026

As e-commerce advertising becomes more competitive, optimizing campaigns for ROAS (Return on Ad Spend) is no longer enough. High revenue doesn't always equal high profit, especially if your best-selli

read more
Google Ads Editor on LinuxA step-by-step guide to installing and running Google Ads Editor with Bottles and Wine

How to Run Google Ads Editor on Linux using Bottles

TutorialsIvanPublished: 15 Oct, 2026

For PPC specialists, media buyers, and agency professionals working on a Linux desktop, Google Ads Editor has long been a missing piece. Google officially provides desktop installers only for Windows

read more
Boost Your ROAS with AlgoShop AITurn hesitant ad clicks into profitable customers with proactive conversational commerce.

Boost Your ROAS with AlgoShop AI Chatbot for Shopify

TutorialsIvanPublished: 04 Oct, 2026

We talk a lot on this blog about optimizing Google Ads and tightening up conversion tracking. But here is a harsh truth for e-commerce brands: you can have the perfect campaign structure, the most ref

read more
Advanced Shopify Webhook TrackingPart II: Google Ads, Server-Side GTM & Stape Store

Advanced Google Ads Tracking for Shopify with Stape & Webhooks

TutorialsIvanPublished: 04 Nov, 2026

Even with a solid Server-Side Google Tag Manager (sGTM) setup running on Stape.io, relying strictly on browser-triggered purchase events still leaves conversion gaps. When shoppers pay th

read more