If you run a business that does not operate in China, Chinese traffic in your analytics is almost always noise. Bot traffic, click farms, referral spam, and crawlers originating from Chinese IP ranges can inflate session counts, skew bounce rates, and — if you are not careful — trigger conversion tags on events that were never real user actions.
You cannot stop the traffic from hitting your site at the GTM level. GTM runs in the browser, so the request has already arrived by the time any tag logic executes. What you can do is prevent your tags from firing for those sessions — which means the data never enters your analytics, your Google Ads conversion counts stay clean, and your remarketing audiences do not get polluted.
Here is how to set it up.
How GTM Knows Where a User Is
GTM does not have a built-in geolocation variable. It cannot read an IP address directly. What it can do is read data that other tools have already determined and placed on the page.
The most practical approach is the Timezone variable. Every browser exposes the user’s local timezone via the JavaScript Internationalization API. China operates on a single timezone: Asia/Shanghai (also reported as Asia/Chongqing, Asia/Harbin, or Asia/Urumqi — all aliases for the same UTC+8 zone).
This is not foolproof — a VPN will report the VPN server’s timezone, not the user’s actual location, and UTC+8 is shared by other countries including Singapore, Taiwan, Hong Kong, and parts of Australia. But for the purpose of filtering obvious bot traffic and bulk spam sessions originating from China, it is accurate enough and requires zero additional tools.
If you need stricter country-level filtering, the alternative is to use a geolocation API call from a Custom HTML tag to get the actual country code — covered at the end of this post.
Step 1: Create the Timezone Variable
In GTM, go to Variables and create a new User-Defined Variable:
- Variable Type: Custom JavaScript
- Name:
JS - User Timezone
function() {
try {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch(e) {
return 'unknown';
}
}
The try/catch handles older browsers that do not support the Intl API — they will return unknown rather than throwing an error and breaking the variable.
Save the variable. You can test it immediately in Preview mode: open any page, check the Variables panel, and you will see your own timezone returned.
Step 2: Create the Blocking Trigger Exception
GTM handles geolocation-based filtering through trigger exceptions. You do not create a trigger that blocks firing — you create a condition that prevents your existing triggers from firing when certain criteria are met.
There are two ways to structure this. The cleaner approach is an Exception trigger added directly to your tags. The broader approach is a blocking trigger applied at the tag level.
Option A: Add an Exception to Existing Triggers
On each trigger you want to protect (All Pages, History Change, click triggers, custom event triggers), add a trigger exception:
Go to the trigger, click Add Exception, and configure:
- Trigger Type: Custom Event (or Page View — pick any type, the condition is what matters)
- This trigger fires on: Some Events
- Condition:
{{JS - User Timezone}}containsAsia/Shanghai
The exception tells GTM: even if the main trigger condition is met, do not fire if this exception condition is true.
The downside of this approach: you have to add the exception to every trigger individually. If you have 20 triggers, that is 20 exceptions to maintain.
Option B: Use a Blocking Trigger Variable (More Scalable)
Create a Lookup Table variable that outputs a value based on the timezone:
- Variable Type: Lookup Table
- Input Variable:
{{JS - User Timezone}} - Name:
LT - Is China Traffic
Add one row:
- Input:
Asia/Shanghai - Output:
true
Set the Default Value to false.
Now create a trigger that fires when this variable is true, and add it as an exception to your tag groups. You only maintain the timezone list in one variable, and the exception references it across all tags.
If you want to add more UTC+8 aliases defensively, add additional rows: Asia/Chongqing, Asia/Harbin, Asia/Urumqi — all mapping to true.
Step 3: Apply the Exception to Your Tags
With the exception trigger configured, apply it to the tags that matter most:
- GA4 Configuration tag — blocks the entire GA4 session from being recorded
- Google Ads Remarketing tag — prevents Chinese IPs from being added to your remarketing audiences
- Google Ads Conversion tags — keeps conversion data clean
- Meta Pixel / CAPI tags — protects your Meta audience quality
You do not necessarily need to apply this to every single tag. Focus on the ones that directly affect your advertising data and analytics reporting.
To add the exception to a tag, open the tag, scroll to the Triggering section, and click the exception icon (the minus sign next to the trigger). Select your China exception trigger.
Step 4: Validate in Preview Mode
To test without traveling to China, you can temporarily override the timezone in your browser’s DevTools.
In Chrome DevTools, open the Sensors panel (three-dot menu, More Tools, Sensors). Under Location, there is a timezone override dropdown. Set it to Asia/Shanghai.
Now reload the page in GTM Preview mode. Your tags should appear in the Tags Not Fired section instead of Tags Fired. If your GA4 Configuration tag is in Tags Not Fired, the blocking is working correctly.
Reset the timezone override when you are done testing.
Alternatively, test directly in the console: open Preview mode, then run Intl.DateTimeFormat().resolvedOptions().timeZone in the console. Confirm it returns what your {{JS - User Timezone}} variable will read.
Handling UTC+8 False Positives
The concern with filtering on timezone is catching legitimate users in Singapore, Hong Kong, Taiwan, the Philippines, Malaysia, and parts of Australia — all UTC+8.
Whether this matters depends on your business. If you have customers in Singapore and want to preserve their data, you cannot use the timezone approach alone.
The targeted alternative: use a country-code check instead of a timezone check.
Add a Custom HTML tag that fires on All Pages and fetches the user’s country from a lightweight IP geolocation API:
<script>
(function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://ipapi.co/json/', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var data;
try {
data = JSON.parse(xhr.responseText);
} catch(e) {
return;
}
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
userCountryCode: data.country_code
});
}
};
xhr.send();
})();
</script>
This pushes the country code (CN for China) into the DataLayer. You then create a DataLayer variable reading userCountryCode and use it as your exception condition: {{DL - Country Code}} equals CN.
The tradeoff: this adds an outbound API request on every page load, which adds latency and depends on a third-party service staying online. For most sites, the timezone approach is accurate enough and has zero performance cost. Reserve the API approach for cases where the UTC+8 false positive risk is a genuine business concern.
What This Does Not Do
A few important boundaries to be clear about:
It does not block traffic from reaching your site. The request still arrives, the page still loads, and your server still processes it. For server-level blocking, you need Cloudflare geo-blocking rules, an .htaccess IP range block, or your hosting provider’s firewall settings.
It does not block JavaScript execution. The GTM container still loads and the Custom JavaScript variable still runs. You are only preventing specific tags from firing.
It does not catch all bots. Sophisticated crawlers do not run JavaScript at all, which means GTM never executes for them. They never appear in your GTM data in the first place. The sessions you are blocking here are ones that do run JavaScript — which includes a significant portion of automated traffic that does execute scripts.
VPNs bypass it. A user in China browsing via a VPN will report the VPN server’s timezone and country. If that server is in Germany, they look like German traffic. Nothing at the client side can reliably detect this.
A Practical Baseline
For most small to mid-size sites seeing China spam in their analytics, the timezone variable approach handles the majority of the problem with minimal setup. Create the variable, add the exception trigger, apply it to your GA4 and Google Ads tags, and validate in Preview with the DevTools timezone override.
The noise in your data drops significantly. Your remarketing audiences stop accumulating irrelevant sessions. Your conversion data reflects actual users.
It is not a complete firewall. It is a clean, maintainable signal filter inside the tool you are already using.
Related Posts
WooCommerce Google Ads Conversion Tracking via GTM Using GTM4WP
14 min read
Why Using Google Tag Manager Is Better Than Adding Scripts Manually
How to Track Email Link Clicks in Google Tag Manager
8 min read
Need Help With Your Google Ads?
I help e-commerce brands scale profitably with data-driven PPC strategies.
Get In Touch