How to Capture GCLID & FBCLID in WooCommerce
WooCommerce doesn't save Click IDs by default. Learn three methods to capture GCLID/FBCLID for order-level attribution, with GDPR compliance guidance.
Tilen Ledic
Written by
If you're running Google or Meta ads for your WooCommerce store, there's something you should know. Every ad click carries a hidden identifier, GCLID or FBCLID, that ties back to the exact campaign, ad, and keyword that brought the visitor. The catch? WooCommerce doesn't save this data with the order. So when a sale comes in, you have no idea which ad actually drove it.
I've seen this trip up a lot of store owners, so I put together this guide to walk you through what these identifiers are, why WooCommerce drops them, and three practical methods to start capturing them.
Before we get into the how, a critical note on consent: If your store serves customers in the EU, UK, Switzerland, or Brazil, all three methods in this guide require user consent before they can run. This is not optional. You need a Consent Management Platform (CMP) in place first. I cover this in detail below, because how much data you can capture depends entirely on where your customers are.
What Is GCLID?
GCLID (Google Click Identifier) is a unique parameter that Google Ads automatically tacks onto every ad click URL. So when someone clicks your ad, they land on something like:
https://your-store.com/product?gclid=EAIaIQobChMI5_Xq...
That string of characters contains encoded data about the campaign, ad group, keyword, and click time. GCLID stays valid for 90 days and it's the backbone of how Google Ads tracks conversions. On iOS devices where the user denies tracking, Google sends gbraid or wbraid instead. I cover all three identifiers and how they differ in a separate comparison.
If you have auto-tagging enabled (which is the default in Google Ads), GCLID gets added to every click automatically. You don't have to do anything.
What Is FBCLID?
FBCLID (Facebook Click Identifier) is Meta's version of the same idea. When someone clicks your ad on Facebook or Instagram, Meta appends an fbclid parameter to the URL:
https://your-store.com/product?fbclid=IwAR3xB2...
FBCLID has a shorter 28-day attribution window and is used for Meta's conversion tracking and ad optimization.
Why WooCommerce Doesn't Capture Click IDs by Default
I want to be clear here: WooCommerce is a solid e-commerce platform. It just wasn't designed with ad tracking in mind. Here's what happens when a visitor lands on your site with a GCLID or FBCLID in the URL:
- The parameter is right there in the URL, but only on the landing page
- As soon as they click to another page, the parameter disappears from the URL
- By the time they place an order, WooCommerce has no record of where they came from
So you end up with an order and zero information about which ad brought it. GA4 tries to fill this gap with browser-side tracking, but it misses 30-50% of conversions because of ad blockers, Safari's ITP, and users declining cookie consent.
That's a lot of missing data if you're trying to figure out which campaigns are actually profitable.
Privacy and Consent: Read This Before Implementing
I'm putting this section before the methods on purpose. The amount of attribution data you can capture depends entirely on where your customers are located. If you skip this section and just copy-paste the code below, you may be breaking the law in certain countries.
The core rule
Storing GCLID or FBCLID in cookies or localStorage counts as non-essential tracking under privacy laws. In opt-in countries (most of Europe, Brazil, Quebec), you must get the user's consent before running any of the code in this guide. In opt-out countries (US, most of Canada, Australia), you can track by default but must allow users to opt out.
The European Data Protection Board (EDPB) confirmed in their Guidelines 2/2023 (final version adopted October 2024) that localStorage is treated identically to cookies under the ePrivacy Directive. Switching from cookies to localStorage does not avoid consent requirements.
What this means in practice by region
| Region | Consent model | Enforcement | Realistic attribution | What to watch out for |
|---|---|---|---|---|
| United States | Opt-out | Low | 95-98% | Disclose in privacy policy. Honor "Do Not Sell" (California, Colorado, etc). |
| Australia | No cookie law (yet) | Very low | 95-98% | Reforms pending for 2026-2027. Disclose in privacy policy. |
| Canada (excl. Quebec) | Opt-out | Low | 90-95% | Disclose and provide opt-out mechanism. |
| Canada (Quebec) | Opt-in (Law 25) | Moderate | 45-60% | Explicit consent required since September 2023. Penalties up to CAD 25M. |
| Slovenia, CEE | Opt-in (same EU law) | Low (for now) | 60-75% | Law is identical to DE/FR. Enforcement is catching up. |
| United Kingdom | Opt-in (PECR + UK GDPR) | Moderate (rising) | 45-60% | ICO cookie sweeps in 2025. Fines aligned to GBP 17.5M / 4% turnover. |
| Switzerland | Opt-in (high-risk profiling) | Moderate | 45-60% | Click ID tracking classified as "intensive intrusion." Criminal penalties up to CHF 250K. |
| Spain | Opt-in (LSSI-CE) | Moderate | 45-60% | Max cookie fine EUR 30K, but GDPR fines apply on top. |
| Italy | Opt-in (Art. 122 CCE) | Moderate | 40-55% | Equal Accept/Reject buttons required. Cookie walls prohibited. |
| Belgium | Opt-in (GDPR direct) | Moderate-High | 40-55% | Daily penalty model: EUR 25-40K per day per site until compliant. |
| Austria | Opt-in (TKG 2021) | Low (rising fast) | 40-55% | noyb (Europe's top privacy activist org) is based in Vienna. |
| Netherlands | Opt-in (Telecommunicatiewet) | High | 35-50% | DPA scans 10,000 websites annually. Warned 50 orgs in April 2025 alone. |
| Germany | Opt-in (TDDDG) | Very high | 30-50% | Fines up to EUR 300K. Court ruled even Google Tag Manager needs consent. |
| France | Opt-in (CNIL) | Strictest globally | 28-40% | CNIL fined Google EUR 325M, SHEIN EUR 150M in 2025 alone. |
| Brazil | Opt-in (LGPD) | Moderate | 50-65% | Over BRL 98M in fines since 2023. Consent is the only legal basis for ad cookies. |
A note on the "realistic attribution" column: These are estimates based on typical consent rates and Click ID capture rates using Method 3. Your actual numbers will depend on how your cookie banner is designed, your audience, and the product you sell. A well-designed banner with a clear value proposition can push consent rates higher. For a deeper dive into how consent laws affect attribution in each country, see our dedicated breakdown.
For US-based stores: You are in the best position globally. With no opt-in requirement and only a 1-5% opt-out rate, you can realistically attribute 95-98% of ad-driven orders using the methods below.
What you need to do before implementing
- Install a CMP (like CookieBot, CookieYes, or Complianz) that blocks tracking scripts until consent is given. This applies to all EU/UK/Swiss/Brazilian visitors.
- Update your privacy policy to mention that you collect advertising click identifiers (GCLID, FBCLID) for measuring ad performance, how long you retain them, and that this data may be shared with Google, Meta, or other ad platforms.
- Set up Google Consent Mode v2 to default "denied" for EEA visitors. This has been mandatory since March 2024 for advertisers using Google services in the EEA/UK/Switzerland. When consent is denied, Google itself redacts GCLID from network requests.
- Accept that in opt-in countries, you will not attribute every order. The goal is to maximize coverage within legal bounds, not to track everyone regardless of consent.
Comparison of Three Methods
Now that you understand the consent landscape, here are the three methods for capturing Click IDs. All coverage percentages below assume the user has consented (or is in an opt-out country where consent is not required).
| Scenario | WooCommerce Built-in | PHP Code (Cookie) | PHP + JavaScript |
|---|---|---|---|
| Same-session purchase | ✓ | ✓ | ✓ |
| Return after 2 hours | Depends on browser | ✓ (24h cookie) | ✓ |
| Return after 3 days | ✗ | ✗ | ✓ (localStorage) |
| Return after 1 week | ✗ | ✗ | ✓ (localStorage) |
| Safari ITP (after 24h) | ✗ | ✗ | ✓ (localStorage) |
Here's the key takeaway: Without the JavaScript solution, you lose the Click ID the moment a customer closes their browser and comes back after more than 24 hours. If you sell higher-priced products where people take a few days to decide, that's a real problem.
Method 1: WooCommerce Built-in Order Attribution
Difficulty: Easy (just a checkbox) Coverage: ~70-80% of same-session orders (for consented users)
Since WooCommerce 8.5+, there's a built-in feature called Order Attribution that captures basic attribution data like UTM parameters and referrer information.
How to Enable
- Go to WooCommerce > Settings > Advanced (or Features in newer versions)
- Check "Order source tracking"
- Save settings
That's it. No code needed.
What You Should Know About Its Limitations
- It relies on session cookies, so when the customer closes their browser, the data is gone
- Safari ITP limits cookies to 7 days (third-party) or just 24 hours for cookies set from ad-click URLs
- It doesn't store the raw GCLID/FBCLID values, only an interpreted source like "google / cpc"
- You can't control how long the data is retained
If your store sells lower-priced items and most customers buy in the same session, this honestly might be all you need. No reason to over-engineer it.
Method 2: PHP Code for Click ID Capture
Difficulty: Medium (copy-paste some PHP) Coverage: ~85-90% of orders from consented users (cookies valid up to 24h)
This method grabs GCLID, FBCLID, MSCLKID, and TTCLID from URL parameters, stores them in cookies, and then writes them to order meta data when the customer checks out.
You need a CMP installed before implementing this. In opt-in countries (EU/EEA, UK, Switzerland, Brazil, Quebec), your CMP must block this code until the user consents to marketing cookies. In the US and other opt-out countries, you can run this without a consent gate, but you should still disclose it in your privacy policy.
How to Install
I'd recommend using the WPCode plugin (it's free) to add this snippet. You can also add it to your child theme's functions.php if you're comfortable with that:
// IMPORTANT: In opt-in countries (EU/UK/CH/BR), this code must only
// run AFTER the user gives cookie consent. Your CMP should block
// this script until consent is granted.
// Capture Click IDs from URL parameters
add_action('init', function() {
$params = ['gclid', 'fbclid', 'msclkid', 'ttclid'];
foreach ($params as $param) {
if (isset($_GET[$param]) && !empty($_GET[$param])) {
$value = sanitize_text_field($_GET[$param]);
setcookie(
'enalitica_' . $param,
$value,
time() + 86400, // 24 hours
'/',
'',
true, // secure
true // httponly
);
}
}
});
// Save Click IDs to order meta data
add_action('woocommerce_checkout_order_created', function($order) {
$params = ['gclid', 'fbclid', 'msclkid', 'ttclid'];
foreach ($params as $param) {
$cookie_name = 'enalitica_' . $param;
if (isset($_COOKIE[$cookie_name]) && !empty($_COOKIE[$cookie_name])) {
$value = sanitize_text_field($_COOKIE[$cookie_name]);
$order->update_meta_data('_' . $param, $value);
}
}
$order->save();
});
Let Me Break Down What's Happening
- A visitor lands on your site with
?gclid=xxxin the URL - The PHP code reads that parameter and stores it in a cookie that lasts 24 hours
- When the customer places an order (even if they browsed around first), the code reads the cookie and saves the Click ID as order meta data
- Now you have the raw GCLID or FBCLID attached directly to the order
Where It Falls Short
- Cookies are limited to 24 hours on Safari for clicks from ad platforms (that's Safari ITP doing its thing)
- If the customer closes their browser and comes back the next day, the cookie is already gone
- It works well for same-session purchases and quick return visits, but not for longer purchase cycles
Method 3: PHP + JavaScript for Full Coverage
Difficulty: Medium (PHP + JS, but it's still copy-paste) Coverage: ~95-98% of orders from consented users (localStorage persists up to 90 days)
This is the most complete approach. It combines the PHP code from Method 2 with a JavaScript snippet that also stores the Click ID in localStorage. The important thing to understand: Safari ITP clears cookies aggressively, but it doesn't touch localStorage.
Same consent rule applies: In opt-in countries, your CMP must block both the PHP and JavaScript code until the user consents. localStorage is treated identically to cookies under the ePrivacy Directive.
JavaScript Code
Add this to your theme's header.php or use the WPCode plugin to inject it on every page:
// IMPORTANT: In opt-in countries (EU/UK/CH/BR), this code must only
// run AFTER the user gives cookie consent. Your CMP should block
// this script until consent is granted.
(function() {
var params = ['gclid', 'fbclid', 'msclkid', 'ttclid'];
var url = new URL(window.location.href);
params.forEach(function(param) {
var value = url.searchParams.get(param);
if (value) {
// Store in localStorage (survives Safari ITP)
localStorage.setItem('enalitica_' + param, JSON.stringify({
value: value,
timestamp: Date.now(),
expiry: Date.now() + (90 * 24 * 60 * 60 * 1000) // 90 days
}));
// Also set cookie for PHP to read
document.cookie = 'enalitica_' + param + '=' + value +
'; path=/; max-age=86400; SameSite=Lax; Secure';
}
});
// Restore cookies from localStorage if they expired
params.forEach(function(param) {
var stored = localStorage.getItem('enalitica_' + param);
if (stored) {
try {
var data = JSON.parse(stored);
if (data.expiry > Date.now()) {
// Restore cookie if it doesn't exist anymore
if (!document.cookie.includes('enalitica_' + param)) {
document.cookie = 'enalitica_' + param + '=' + data.value +
'; path=/; max-age=86400; SameSite=Lax; Secure';
}
} else {
localStorage.removeItem('enalitica_' + param);
}
} catch(e) {}
}
});
})();
Here's Why This Makes Such a Difference
Let me walk you through a real scenario:
- Customer clicks your ad > GCLID/FBCLID gets stored in both localStorage and a cookie
- Safari deletes the cookie after 24 hours > but localStorage still has the value
- Customer comes back 3 days later to buy > JavaScript restores the cookie from localStorage
- Customer places the order > PHP reads the cookie and saves the Click ID to the order
This really matters if you sell products where people take time to decide. Think furniture, electronics, or anything over a couple hundred euros. Those customers almost never buy on the first visit.
A Quick Note on Compatibility
You can use Methods 1 and 3 together. They don't conflict with each other. WooCommerce's built-in tracking handles session-level data, while the PHP + JS code captures the raw Click IDs. Running both gives you the best coverage.
How Enalitica Uses Click IDs
Once the Click ID is stored with the order, here's what becomes possible:
Order-level attribution. Each order gets linked to the exact campaign, ad group, and keyword that triggered the click. For users who consented (or in opt-out countries like the US), this gives you precise, observed attribution, not statistical modeling. Once you have click IDs on your orders, you can also build multi-touch attribution models that credit every touchpoint in the customer journey, not just the last click.
Accurate ROAS. You can see actual revenue by campaign based on real orders, not GA4 estimates that are missing a significant chunk of conversions due to ad blockers, consent denial, and cookie expiration.
Server-side conversion tracking. Enalitica sends conversions back to Google Ads (Enhanced Conversions) and Meta Ads (Conversions API) from your server, bypassing browser-side ad blockers entirely. This gives ad platforms better optimization signals for your actual buyers.
Long-term analysis. With up to 5 years of stored data, you can look at seasonal trends, customer lifetime value by channel, and the long-term impact of individual campaigns.
What about users who don't consent? In opt-in countries, users who decline cookie consent will not have a Click ID attached to their order. Enalitica can still show you these orders, but they will appear without ad attribution. This is the correct, legal behavior. The goal is to maximize the quality and completeness of data from consented users, and Enalitica's server-side approach eliminates the additional losses from ad blockers and cookie expiration that browser-based tools like GA4 suffer from.
What Google and Meta Do When Consent Is Denied
Understanding this helps set expectations for your attribution coverage in opt-in markets.
Google Consent Mode v2 (mandatory since March 2024 for EEA/UK/Swiss advertisers): When a user denies consent, Google redacts GCLID from network requests and GA4 sends anonymous pings without cookies. Google then applies conversion modeling to estimate missed conversions, claiming approximately 70% recovery. However, this requires a minimum of 700 ad clicks over 7 days per country and domain, so smaller advertisers may not qualify. Even with modeling, modeled data is an estimate, not observed reality.
Meta Consent Mode: When consent is denied, the Meta Pixel switches to privacy-preserving mode and CAPI filters personal data, sending only aggregated signals. Meta applies statistical modeling similar to Google's approach.
The bottom line: consent denial creates a real data gap. The methods in this guide give you the best possible coverage for users who do consent, and Enalitica's server-side approach ensures you don't lose additional data to browser limitations on top of consent losses.
Frequently Asked Questions
Do I need to update my privacy policy when capturing Click IDs?
Yes, and this is something a lot of store owners overlook. If you're storing GCLID or FBCLID in cookies or localStorage, that counts as data processing under GDPR. Your privacy policy should mention that you collect advertising click identifiers for the purpose of measuring ad performance. If you're using a Consent Management Platform (CMP), make sure Click ID capture only fires after the user gives consent for marketing or analytics cookies.
Will this work with WooCommerce Blocks checkout?
If your store uses the newer WooCommerce Blocks-based checkout instead of the classic shortcode checkout, the PHP code from Methods 2 and 3 still works fine. The woocommerce_checkout_order_created hook fires regardless of which checkout type you use. Just make sure you're on WooCommerce 8.0+ where this hook is stable for both checkout flows.
What about Microsoft Ads (MSCLKID) and TikTok (TTCLID)?
The code in this guide already handles both. MSCLKID works the same way as GCLID but for Microsoft Ads (Bing), and TTCLID is TikTok's click identifier. Both get captured, stored, and saved to order meta data alongside GCLID and FBCLID. If you're running ads on these platforms too, you're covered without any extra setup.
How do I verify that Click IDs are actually being captured?
The simplest way: visit your store with ?gclid=test123 appended to the URL, place a test order, then check the order in WooCommerce admin. Go to the order details and look for a custom field called _gclid with the value test123. If it's there, everything is working. You can also check your browser's Developer Tools (Application tab > Cookies and localStorage) to confirm the values are being stored on the frontend side.
Can I use Click IDs alongside GA4?
Absolutely, and I'd actually recommend it. They serve different purposes. GA4 gives you session-level analytics like page views, user behavior, and funnel analysis. Click IDs stored on orders give you hard revenue attribution at the order level. Think of GA4 as your "what happened on the site" tool, and Click ID attribution as your "which ad made money" tool. They complement each other well.
What if I'm using a caching plugin?
This is a good one. Full-page caching plugins (like WP Rocket, LiteSpeed Cache, or W3 Total Cache) can sometimes cache the landing page before the PHP code runs, which means the Click ID parameter might not get read from the URL. The fix: exclude pages with gclid, fbclid, msclkid, or ttclid query parameters from the cache. Most caching plugins let you add query string exceptions in their settings. The JavaScript part (Method 3) is unaffected by caching since it runs in the browser.
What is the difference between GCLID and UTM parameters?
UTM parameters (utm_source, utm_medium, utm_campaign) are ones you set manually and they contain general campaign info. GCLID is generated automatically by Google and contains precise click-level data including the keyword and ad group. Here's the practical difference: with UTMs, you know "this came from Google Ads, summer campaign." With GCLID, you can trace back to the exact keyword, ad variation, and time of click. If you're spending serious money on ads, that level of detail matters.
Is my US store affected by any consent requirements?
Not significantly. The US has no federal cookie consent law and no opt-in requirement. You must provide a "Do Not Sell or Share" opt-out link for California (CCPA/CPRA) and honor Global Privacy Control signals in a handful of states. The practical opt-out rate is 1-5%, meaning you retain attribution data for 95%+ of your traffic. If you sell primarily to US customers, the methods in this guide give you near-complete attribution coverage without any consent complexity.
How often should I audit my attribution setup?
I'd suggest checking at least once a quarter. Browser privacy policies change, WooCommerce updates can affect hooks, and caching plugin updates might reset your exclusion rules. A quick audit looks like this: place a test order with a fake GCLID, verify it shows up in the order meta, and check that your localStorage values persist across browser sessions. It takes 10 minutes and can save you months of lost attribution data.
See your real numbers
Enalitica tracks orders server-side and shows you exactly which campaigns drive revenue. See what's possible in your market.
Book a Demo