What is CAPI (Conversion API)?
CAPI (Conversion API) allows you to send conversion data directly from your server to Google Ads, bypassing browser-based tracking entirely. Instead of relying on JavaScript tags that can be blocked by ad blockers, restricted by browser privacy settings, or broken by iOS restrictions, you upload conversion events via the Google Ads API after the sale has completed on your server.
How It Works
When a customer completes a purchase, your server captures the GCLID (Google Click ID) that was stored at the point of ad click, then sends the conversion data — GCLID, order value, timestamp — directly to Google Ads via the API. This happens server-to-server, so ad blockers, cookie restrictions, and browser privacy settings do not affect it.
CAPI vs Client-Side Tracking
| Feature | Client-Side (gtag.js) | Server-Side (CAPI) |
|---|---|---|
| Ad blocker impact | Blocked (15–30% loss) | Not affected |
| iOS privacy (ATT) | Limited by opt-outs | Bypassed |
| Cookie lifespan (Safari) | 7-day maximum (ITP) | Server-controlled — 90+ days |
| Cross-device tracking | Limited | Better attribution via user identifiers |
| Offline / in-store sales | Not possible | Fully supported |
| Data accuracy | 50–70% of actual | 85–95%+ of actual |
Conversion Types Supported
- Click conversions — Purchases, signups, or leads that happen after an ad click (requires GCLID)
- Call conversions — Phone orders tracked through call tracking systems
- Store sales — In-store purchases attributed to online ad exposure
- Enhanced conversions — Conversions enriched with first-party customer data (email, phone, address) for fallback matching
Why CAPI Matters for E-Commerce
For Google Shopping advertisers, conversion data directly impacts Smart Bidding performance. Missing conversions mean Google's algorithms make decisions on incomplete information — undervaluing your best products and misallocating budget.
The Impact on Your Campaigns
Without accurate conversion data, Smart Bidding makes systematically bad decisions. It sees a product convert at 1.2% when the true rate is 1.8%, and bids accordingly — starving profitable products of budget while overspending on visible-but-mediocre ones. Here is what this looks like in practice:
| Scenario | Without CAPI | With CAPI |
|---|---|---|
| Conversion visibility | 50–70% of actual sales | 85–95%+ of actual sales |
| Reported ROAS | Lower than reality | Accurate |
| iOS/Safari orders | Largely untracked | Fully captured |
| Remarketing audiences | Smaller, incomplete | Full purchaser lists |
| Smart Bidding quality | Based on partial data | Based on complete data |
Why Accurate Data Enables Profit Optimisation
Tracking accuracy is not just a reporting problem — it directly impacts bid optimisation. When 30% of conversions are invisible to Google, Smart Bidding operates blind. Profit-based bidding tools like ProfitClarity include a tracking accuracy adjustment that compensates for known loss rates, but the foundation is always accurate server-side data. CAPI is that foundation.
2026 API Changes
Starting February 2, 2026, new developers can no longer use session attributes or raw IP address data in Google Ads API conversion imports. Google is consolidating conversion import under the Data Manager API. If you are building a new CAPI integration, target the Data Manager API from the start rather than the legacy ConversionUploadService.
Step 1: GCLID Capture & Storage
The GCLID (Google Click ID) is the critical link between an ad click and a conversion. When someone clicks your Google ad, a unique identifier is appended to the landing page URL:
https://yourdomain.com/product?gclid=EAIaIQobChMI...Your job is to capture this parameter, persist it through the shopping journey, and store it alongside each order in your database.
Step 1a: Enable Auto-Tagging
- In Google Ads, go to Settings → Account Settings
- Enable Auto-tagging
- This automatically appends
gclidto all ad click destination URLs
Step 1b: Capture GCLID on Your Site
Add this script to every page to capture GCLIDs from the URL and store them for later use. It also captures wbraid and gbraid — Google's iOS web and app attribution parameters:
// GCLID Capture Script — place on every page
(function() {
const CONFIG = {
GCLID_KEY: 'grow_gclid',
EXPIRY_DAYS: 90
};
function getGclidFromUrl() {
const params = new URLSearchParams(window.location.search);
return params.get('gclid') ||
params.get('wbraid') || // iOS web fallback
params.get('gbraid'); // iOS app fallback
}
function storeGclid(gclid) {
if (!gclid) return;
// localStorage (primary storage)
localStorage.setItem(CONFIG.GCLID_KEY, gclid);
localStorage.setItem(CONFIG.GCLID_KEY + '_ts', Date.now());
// Cookie (backup — survives localStorage clear, works cross-subdomain)
const expires = new Date(Date.now() + CONFIG.EXPIRY_DAYS * 86400000);
document.cookie = CONFIG.GCLID_KEY + '=' + gclid +
';expires=' + expires.toUTCString() +
';path=/;SameSite=Lax;Secure';
}
const gclid = getGclidFromUrl();
if (gclid) storeGclid(gclid);
})();Step 1c: Pass GCLID Through Checkout
Add a hidden field to your checkout form so the GCLID is submitted with the order:
<!-- Add to checkout form -->
<input type="hidden" name="gclid" id="gclid_field">
<script>
// Populate hidden field with stored GCLID
document.getElementById('gclid_field').value =
localStorage.getItem('grow_gclid') || '';
</script>Step 1d: Store GCLID in Your Database
Add GCLID columns to your orders table. Index the column for efficient lookup during upload jobs:
-- Database schema additions
ALTER TABLE orders ADD COLUMN gclid VARCHAR(255);
ALTER TABLE orders ADD COLUMN gclid_type VARCHAR(20); -- 'gclid', 'wbraid', or 'gbraid'
ALTER TABLE orders ADD COLUMN conversion_uploaded_at TIMESTAMP;
ALTER TABLE orders ADD INDEX idx_gclid (gclid);GCLID is Case-Sensitive
Store and upload GCLIDs exactly as received — do not modify, truncate, lowercase, or trim the value. The GCLID must match Google's records character-for-character for conversion attribution to succeed. A single incorrect character means the conversion is silently rejected.
Step 2: Create Conversion Actions in Google Ads
Before uploading conversions via the API, you need a dedicated conversion action configured for offline/server-side imports. Do not use the same conversion action as your website tag — keep them separate so you can diagnose issues independently.
Create the Conversion Action
- In Google Ads, go to Goals → Conversions → Summary
- Click + New conversion action
- Select Import → Other data sources or CRMs
- Choose Track conversions from clicks
- Configure the settings below
| Setting | Recommendation | Notes |
|---|---|---|
| Name | "Server-Side Purchase" or "CAPI Purchase" | Keep distinct from tag-based actions |
| Category | Purchase | Match your conversion type |
| Value | Use different values for each conversion | Pass actual order value or profit |
| Count | Every (for purchases) | Use "One" for leads or signups |
| Click-through window | 90 days | Match your GCLID storage duration |
| Attribution model | Data-driven (if eligible) | Falls back to last-click for new accounts |
Get the Conversion Action Resource Name
After creating the action, note the Conversion Action ID from the URL or the API. You will need it in this format for upload requests:
customers/{customer_id}/conversionActions/{conversion_action_id}Use a Separate Test Conversion Action
Create a second conversion action for development and testing. Uploading test conversions to your production action corrupts your data and can confuse Smart Bidding. Label it clearly (e.g. "CAPI Purchase — TEST") and never include it in bidding.
Step 3: Upload Conversions via the Google Ads API
With GCLIDs captured and a conversion action created, you can now upload conversions. The API endpoint is ConversionUploadService.UploadClickConversions. For new implementations from early 2026 onwards, Google recommends the Data Manager API.
API Requirements
- Developer token — Request via your Google Ads account under Tools & Settings → API Center
- OAuth 2.0 credentials — Service account or web app credentials from Google Cloud Console
- Customer ID — Your Google Ads account ID without dashes (e.g.
1234567890) - Conversion Action resource name — From the conversion action you created
Conversion Upload Payload
Each conversion requires these fields. The order_id field is critical — it acts as an idempotency key and prevents duplicate uploads if your retry logic fires more than once for the same order:
{
"gclid": "EAIaIQobChMI...", // Required — exact as captured
"conversion_action": "customers/123/conversionActions/456",
"conversion_date_time": "2026-03-23 14:30:00+00:00", // ISO format with timezone
"conversion_value": 99.99, // Order total OR profit value
"currency_code": "GBP", // ISO 4217 currency code
"order_id": "ORD-12345" // Prevents duplicate uploads
}Upload Frequency and Batching
| Parameter | Recommendation | Reason |
|---|---|---|
| Batch size | 100–500 conversions per call | Balance throughput vs API latency |
| Trigger method | Event-driven on order completion | Minimises latency from seconds to minutes |
| Fallback schedule | Every 15 minutes for any pending queue | Catches orders that missed the event trigger |
| Retry logic | Exponential backoff — 30s, 2m, 10m | Handles transient API failures gracefully |
| Error handling | Log partial failures, mark uploaded rows | API can partially accept a batch |
Don't Batch Daily
Uploading conversions once per day is far too slow for Smart Bidding. Google's algorithms need fresh signals to optimise bid decisions in real time. Upload within 15 minutes of order completion for maximum bidding benefit. Event-driven uploads (triggered on the order webhook or post-payment hook) are ideal.
Step 4: Enhanced Conversions for Better Match Rates
Enhanced conversions add hashed first-party customer data to your conversion uploads. When a GCLID is missing, expired, or never captured, Google can still match the conversion to an ad click by matching the customer's hashed email or phone number against signed-in Google account data.
User Identifiers to Include
- Email address — Most important, highest match rate. Normalise before hashing.
- Phone number — E.164 format (
+441234567890) - First name and last name — Lowercase, no special characters
- Street address, city, state, postal code, country — Match to Google account billing info
Data Normalisation and Hashing
All user data must be normalised and hashed with SHA-256 before leaving your server. Google only receives the hash — never the raw data:
// Node.js — normalise and hash before upload
const crypto = require('crypto');
function hashForEnhancedConversions(value, type = 'email') {
let normalized = value.trim().toLowerCase();
if (type === 'email' && normalized.includes('@gmail.com')) {
// Gmail: remove dots from the username portion
const [username, domain] = normalized.split('@');
normalized = username.replace(/./g, '') + '@' + domain;
}
if (type === 'phone') {
// Remove all non-digit characters, then prepend country code if missing
normalized = normalized.replace(/D/g, '');
if (!normalized.startsWith('+')) normalized = '+' + normalized;
}
return crypto.createHash('sha256').update(normalized).digest('hex');
}
// Example usage
const hashedEmail = hashForEnhancedConversions('John.Doe@Gmail.com', 'email');
const hashedPhone = hashForEnhancedConversions('+44 7700 900123', 'phone');
// Include these hashes in your conversion upload payloadMulti-Layered Matching
Enhanced conversions create a fallback hierarchy so Google can attribute conversions even when your primary signal is missing:
- Primary match — GCLID directly links the conversion to a specific ad click
- Fallback match — Hashed email or phone matches to a signed-in Google account
- Cross-device recovery — Customer clicks on mobile, converts on desktop; email links the journey
- Cookie deletion recovery — GCLID cookie expired, but email match bridges the gap
Privacy and Consent Compliance
Hashing happens on your server before any data leaves. Google receives only hashes — the raw email or phone cannot be reverse-engineered. For EEA and UK users, you must also pass consent signals (ad_user_data: GRANTED) in your upload payload per Consent Mode v2 requirements. Do not upload enhanced conversion data for users who have not consented to ad personalisation.
Best Practices
Data Quality Checklist
- Unique order IDs — Always include
order_idto prevent duplicate conversions on retries - Accurate values — Use actual order totals or actual profit — never placeholder or average values
- Correct timestamps — Always include timezone offset (e.g.
2026-03-23 14:30:00+00:00) - GCLID preserved exactly — Store and upload the value character-for-character as received
- Multiple identifiers — Email + phone + address gives the highest match rate
- 90-day retention — Store GCLIDs long enough to cover your full attribution window
- Mark uploaded rows — Track
conversion_uploaded_atto avoid re-uploading
Profit-Based Conversion Values
Most brands upload order revenue as the conversion value. Smart Bidding then optimises for revenue — treating a £10 profit sale the same as a £60 profit sale. This is a fundamental misalignment between what you tell Google to optimise for and what actually matters to your business.
MarginStack solves this by computing true per-order profit (after COGS, shipping, payment fees, return costs, and platform fees) and passing that value as the conversion value in the CAPI upload. Google's algorithms then optimise for actual profit, naturally bidding higher on high-margin products and pulling back on low-margin ones.
| Approach | Conversion Value Uploaded | What Google Optimises For |
|---|---|---|
| Revenue-based (standard) | £99.99 (order total) | Maximum revenue — margin-blind |
| Profit-based (MarginStack) | £35.00 (actual profit) | Maximum profit — favours high-margin SKUs |
Layer CAPI with Tag Gateway
CAPI and Tag Gateway are complementary, not alternatives. Together they give you the most complete tracking picture possible:
| Layer | What It Does | Coverage |
|---|---|---|
| Tag Gateway | First-party script proxy, bypasses browser ad blockers | ~85–95% of browsing sessions |
| CAPI | Server-side upload of completed sales | 100% of orders placed |
| Enhanced Conversions | Hashed user data fallback matching | Adds 5–17% attribution on top |
Monitoring & Diagnostics
CAPI is not a set-and-forget system. Monitor these metrics weekly to catch issues before they affect campaign performance.
Key Metrics to Track
| Metric | Healthy Target | Action if Below Target |
|---|---|---|
| GCLID capture rate | 40–60% of orders | Check script placement, verify auto-tagging is on |
| Upload success rate | 95%+ of attempted uploads | Check GCLID validity, timestamp format, API auth |
| Enhanced conversion match rate | 80%+ | Add more user identifiers, check normalisation logic |
| Data freshness | <15 minutes after order | Switch from scheduled batches to event-driven uploads |
| Duplicate conversion rate | <1% | Ensure order_id is always included, check retry logic |
Google Ads Diagnostics
- Go to Goals → Conversions → Summary in Google Ads
- Click your CAPI conversion action
- Open the Diagnostics tab
- Review: upload status, error breakdown, match rate for enhanced conversions, and recommended improvements
Compare CAPI vs CRM Totals Monthly
Run a monthly reconciliation: compare conversions recorded in Google Ads against orders in your CRM or order management system for the same date range. A large gap (more than 15%) indicates a capture or upload issue. Small gaps (5–10%) are normal due to attribution windows and non-Google traffic.
Implementation Roadmap
A practical 8-week timeline for getting CAPI live and fully optimised:
| Phase | Tasks | Outcome |
|---|---|---|
| Weeks 1–2: Foundation | Enable auto-tagging; deploy GCLID capture script; add database columns; test GCLID flows through checkout | GCLIDs stored on new orders |
| Weeks 3–4: API Integration | Request developer token; set up OAuth 2.0; build conversion upload service; test with 10–20 conversions | First successful API uploads |
| Weeks 5–6: Enhanced Conversions | Capture first-party data at checkout; implement normalisation and SHA-256 hashing; add to upload payload; monitor match rate | 80%+ match rate in diagnostics |
| Weeks 7–8: Optimisation | Switch to event-driven uploads; set up monitoring alerts; implement profit-based conversion values; verify Smart Bidding improvement | Full system live, measurable improvement |
Expected Results After Full Implementation
- 15–25% increase in tracked conversions
- 5–17% improvement in Smart Bidding performance
- 80%+ match rate for GCLID and user identifier combinations
- Recovery of iOS and ad-blocker blocked conversions that were previously invisible
- Accurate ROAS reporting that reflects real business outcomes
Next Steps
CAPI is the tracking foundation that every other optimisation layer depends on. Once your server-side conversion data is flowing accurately, you can layer on profit-based bidding, SKU-level ROAS targets, and automated campaign management.
GROW Your Sales Handles This For You
The GROW Your Sales includes built-in CAPI infrastructure: GCLID capture, server-side conversion uploads, enhanced conversion hashing, and profit-based conversion value calculation via MarginStack. Instead of building and maintaining this pipeline yourself, connect your store and your conversions start flowing immediately. Create a free account to see how it works with your data.
Related Reading
- Tag Gateway: First-Party Tracking via Cloudflare — Layer server-side script proxying on top of CAPI
- How to Win with Google Shopping in 2026 — The full strategic picture for profitable Shopping campaigns
- COGS & CAC: Understanding Your True Margins — Build the cost data that powers profit-based bidding