The Art Of The Double Negative — Using Trigger Exceptions In Google Tag Manager

June 23, 2020 | Jon Meck
The Art Of The Double Negative — Using Trigger Exceptions In Google Tag Manager blog image

Besides the basics of adding analytics and marketing tags to your website, Google Tag Manager also enables advanced website tagging and management through the strategic use of Triggers. Understanding the basics of Trigger conditions, multiple Triggers, and Trigger exceptions will help to make your container smaller, more agile, and more effective.

Let’s go through some basics, and then really dive into Trigger exceptions.

Triggers and “Events”

When you start creating a Trigger, the wizard does a great job of forcing you to start with a specific Event. This is a different concept than in Google Analytics (GA), and equates to specific “actions” that happen on the page. Popular Events are when a Page starts loading, a PDF link is clicked, or a form is submitted.

image showing selection of trigger types in google tag managr

When you choose a specific type of Event, Google Tag Manager (GTM) will do the hard part and “listen” for those events. As the events occur, GTM will look for any Triggers that are associated with that Event, then check the next part we’ll discuss—the Trigger Conditions.

Trigger Conditions

There are only a few instances where we’d want to fire a Tag on every Page load, or on every link click. Rather, we need a way to focus in on specific pages or specific actions. For instance, once we’ve identified that someone clicked on a link, we can start to be more specific by adding conditions. This is the part where we narrow in on just PDF links or just Blog pages.

In addition, we have the option to include multiple conditions. Let’s say I only wanted to track PDF links that also contain the word “analytics” in the link, I could do this with multiple conditions.

image example of setting up trigger conditions in google tag manager

Trigger conditions must ALL evaluate to TRUE for the Trigger to fire.

What happens when I want a Trigger for PDF files that contain either “analytics” or “google ads”

Well, like most things Google, there are multiple ways to accomplish the same task. It might be tempting to include both of these as separate conditions, but this wouldn’t work, as all the conditions need to be TRUE in order for the Trigger to fire.

image example of how trigger conditions can be wrongly set up

In this case, I could modify the Trigger we just created and use a regular expression that matches either “analytics” or “google ads.”

image example of trigger conditions correctly set up

I would then want to rename this Trigger to indicate that it will now fire on both Analytics and Google Ads PDF Downloads.

Multiple Triggers

Sometimes a better solution would be to use multiple Triggers. A helpful question to ask yourself would be, “Would I ever use this Trigger for another Tag?” You can reduce the number of overall Triggers by creating more general Triggers that are applicable to many Tags, then adding multiple Triggers when necessary.

A Tag will fire if ANY of the Triggers evaluate to TRUE.

Depending on your needs, it may be more helpful to have two Triggers for “Analytics PDF Downloads” and “Google Ads PDF Downloads” than a single Trigger that says “Analytics Or Google Ads PDF Downloads.” Then we can use these for remarketing Tags, Google Analytics Tags, anything we like!

Let's take this Trigger and split into two separate Triggers and add them to the same Tag.

There’s another important note to throw in here. What if the fates aligned and we happened to have a PDF that contained both the words “analytics” and “google ads”? I often get asked, if there are two Triggers, won’t that mean that the Tag will fire twice?

The answer is usually, “No.” Remember that each Trigger is associated with some sort of Event, like the page loading or a click on a link.

A Tag will only fire ONCE per Event.

So, if a link is clicked on, and it happens to be a PDF about both Google Analytics and Google Ads, both Triggers will match, but since they’re both tied back to the same Link Click event, the Tag will only fire once.

Trigger Exceptions

Now we’re getting to the good stuff! Sometimes we fall into the trap of using the Trigger conditions to say both when we DO want something to fire and at the same time when we DON’T want something to fire. Depending on your scenarios, this may make complete sense, but often this can result in a long list of Triggers that repeat a significant amount within them. Often, the reasons we don’t want a Tag to fire can be used over and over again, like blocking certain Tags from firing on mobile devices or separating Tags that should fire on our Dev and Live versions of the website.

In our example, we currently have two Triggers that will fire, one for PDFs with the word “analytics” and one for PDFs with the word “google ads.” Let’s say I’d like to make sure these Tags only fire on our Live Site. In this example, if the link is on our live site, which has a hostname of “”, then it’s ok to fire. If it’s on our dev site, which we’ll pretend is “”, then I don’t want it to fire.

You might think that we can just continue adding more conditions to our Triggers, like below. This method works, but it would not be my recommendation.

image showing how you can setup multiple trigger conditions

This method is a little more clunky and a little harder to manage. If we want to test it on our Dev site first, we’d have to go through and change each condition in each Trigger, then change it back to Live when we’re ready to go.

Enter the Trigger Exception! These are special Triggers that we can use to block Tags from firing in certain instances. This may require a bit of twisting in our logic. If we want these Tags to only fire on our Live site, then we can create a Trigger Exception, or a blocking Trigger, that says— “Do NOT fire if you are NOT on the Live site.”

Let’s look at this a little more closely and examine the double negative. If we use this as a Trigger exception, then it says the following:

“Block this Tag from firing when the user is not on

which can be reworded as:

“Only fire this Tag when the user is on

The benefit here is that this is a Trigger that we’ll use over and over again. For instance, once we make sure our marketing Tags are firing properly, we’ll want to stop those from firing on our dev site as well.

Trigger exceptions are created just like normal Triggers, with a few minor differences. If you went through the GTM V2 Migration, you’ll notice that the GTM Team took care of this for you, and I really like the naming structure they used. I like to start all of my blocking Triggers with “Blocking – ”, which just helps me keep my list of Triggers organized.

Remember how all Triggers must be tied to an event? In this case, we’re going to make an exception and say that instead of tying a blocking Trigger to a specific event, we’re going to block any event, if the conditions match. We can do this with a little bit of regular expression, saying that the event is equal to .* which just means, it can be any event.

image of event name field with box checked next to it that says use regex matching

Once we have the Trigger created, we can add it to a Tag by clicking the “Add Exceptions” link at the bottom of the Tag.

image showing complete trigger with the option to add exception highlighted

Then we just choose the Trigger we created, and we’ll see it show up in a special section. Just like regular Triggers, we can add multiple Trigger exceptions to the same tag.

If ANY Trigger Exceptions evaluate to True, then the Tag will be blocked from firing for that event.

It’s also helpful to use the GTM Debug Panel to help see why a specific Tag did or did not fire, particularly showing you the specific Triggers that did or did not evaluate to true (the green checkbox).

Why Use Trigger Exceptions?

What’s the big deal? Why should we be using Trigger Exceptions? I’ll give you a few reasons.

Less Clutter, Less Confusion

I mentioned it before but it’s worth repeating, if we can find ways to break apart Triggers into reusable components, then we can effectively reduce the number of total Triggers that we have to maintain.

Separate Function from Everything Else

Triggers fire when something happens. When possible, try to keep the job of a Trigger to be only the action you’re trying to capture. We can use Trigger exceptions to control for other things, like information about the User (mobile or desktop), information about the environment (Live or Dev), or the frequency of the Tag firing.

Maintenance and Upkeep

Trigger exceptions also make it easier to manage where and when a Tag fires. When using a shared GTM container, we can set up the Tag and the Trigger that we’re working on, and use blocking Triggers to control whether or not these are ready to go to production.

A Great Big List of Blocking Triggers

And with our (not so) brief introduction complete, here is a big ole’ list of blocking Triggers you can create and their use cases. One note – the naming is important so that you understand exactly what these Triggers are doing. I’ll give you suggestions, but feel free to rename so that it makes sense to you!

1. Blocking – Regular Site Visitors

Variables: Debug Mode (Built-In Variable)

Use Case: This Trigger exception uses the built-in Debug Mode variable to identify if someone is previewing the website in Debug mode. Only a logged-in GTM user can preview a container, which means only a logged-in GTM user can be in Debug mode.

This is an excellent blocking Trigger, as it lets us work on a Tag and see it in action while we’re previewing a container, but it won’t be visible to anyone visiting our site, even if the container gets accidentally published. When I create a new Tag, I immediately add this exception to block it from All Site Visitors, until I’m ready for it to go live on the site. If you have multiple people or agencies working with GTM, this Trigger is a must-have!

Remember the double negative – Block tags from firing if debug mode is equal to false, or if we flip that around, only fire tags when the user is currently in Debug mode.

image of list of errors with debug mode selected


2. Blocking – GTM Debug Mode

Variables: Debug Mode (Built-In Variable)

Use Case: This Trigger exception just flips the operator, saying that we’ll block Tags from firing if we ARE in debug mode. This is handy for Tags that are already working properly, but that we don’t want to fire while we’re debugging our site.


For instance, if we’re putting in test transactions, we can add this Trigger exception to all of our conversion Tags, so they don’t send out fake transaction details to Facebook, Google Ads, Analytics, etc.

3. Blocking – Live Site

Variables: Page Hostname (Built-In Variable)

Use Case: If you have a website that has multiple environments, like different staging or development servers, this Trigger Exception is so helpful in helping to control which Tags are still in Dev Mode and which ones are ready for prime time. Again, throw this exception on anything that is not ready to go live.

image of list of pages with box checked next to page hostname


4. Blocking – Dev Site

Variables: Page Hostname (Built-In Variable)

Use Case: Now let’s flip this around and do the reverse—block Tags from firing on our Dev site. This is especially important for anything that would measure conversions. While we often want to keep the environment exactly the same to make sure everything places nicely together, it can be helpful to hide select Tags from firing. Email marketing, remarketing tags, surveys or popups, Google Trusted Store badge, Live Chat—you name it! If it’s working properly, remove it from your Dev site. 

5. Blocking – Other Site

Variables: Page Hostname (Built-In Variable)

Use Case: There are a few cases when it makes sense to have the same GTM container on completely different domains. Perhaps they share a similar template, or you just want to streamline your tagging. These blocking Triggers can be used to dictate which Tags will fire on which sites. Remember the double negative—if I want it to fire on, I’ll create a blocking rule for anything that is not equal to

6. Blocking – Not First Page

Variables: Referrer (Built-In Variable)

Use Case: The HTTP Referrer is a helpful piece of information that tells you what the previous page was that “referred you” to the current page. This is the underpinning of Google Analytics traffic attribution and with some notable exceptions, like going from HTTPS to HTTP, we can use this in a variety of ways.

In this example, we’re saying that we want to block a Tag from firing if a user visits a page on our website and if the previous page was also our website. In other words, we only want this Tag to fire on the first page of someone’s session. This can be great for pop-ups, promotions, or messaging that may be bothersome to continually show a user.

Think about how you could also use this to fire different Tags when someone comes from a specific referring site!

7. Blocking – 80 Percent

Variables: Random Number (Built-In Variable)

Use Case: This method goes all the way back to a blog post from Dan Russell, with some notable changes. Rather than creating a Firing Trigger for a random sample, we’ll use a Trigger exception. Again the benefit is that we can use the Firing Triggers to deal with the conditions that are required for the Tag to fire, and we use the Trigger exception to just control the frequency of the Tag firing.

The Random Number variable gives us just that, a random number. We can use a simple regular expression to match when the final digit in that random number is anything from 1-8. That will occur 80 percent of the time, with the other 2 options being a 9 or a 0.

Let’s change our perspective again—if we’re blocking this Tag from firing 80 percent of the time, then what we’re really saying is “Fire this Tag 20 percent of the time.” Important to note here, every time a page loads, it will be checking this Trigger. So, this is not necessarily a way to only show a Tag to 20 percent of your site’s visitors.

image of list of utilities with boxes checked next to event and random number


8. Blocking – Not Analytics Related

Variables: Page URL (Built-In Variable)

Use Case: If I want to fire a specific Tag just for visitors that are on a page that is related to Google Analytics, I can block all traffic on pages that are not related to Google Analytics. Of course, adapt this to fit your specific site structure, or with your specific subdirectories.

9. Blocking – Mobile

Variables: Is Mobile (Custom JavaScript Variable)

Use Case: Now let’s get into some of the fun stuff we can do with Custom JavaScript Variables! We’ve been using Built-In Variables, but we can greatly extend our capabilities by using some custom JavaScript. For this one, we’ll create a Variable that checks the User Agent to attempt to determine if the visitor is on a mobile device. Simo Ahava has a good mobile Variable adapted from, so we’ll just use that one! (Thanks!) The variable gives a simple true or false, which answers the question: “Is the visitor on a mobile device?” 

This is a great exception to use for any Tag that pops up a message or would provide a negative experience to a user on a mobile device.

function () {
  var a = navigator.userAgent || navigator.vendor || window.opera;
  if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) { return true; }
  return false;

10. Blocking – Desktop

Variables: Is Mobile (Custom JavaScript Variable)

Use Case: Let’s flip the operator here and just look for the reverse—if someone is not on a mobile device, then we assume they’re on a desktop. This is our way of firing specific Tags just for mobile visitors, like geolocation, etc.

11. Blocking – Internal – IP

Variables: IP Address (Data Layer Variable)

Use Case: Jon Meck, Bounteous VP of Marketing,  wrote about this in a post about using Blocking Rules instead of Exclude Filters. You can reference that previous post for more information about the server setup, but for a quick summary—if we can get the user’s IP address on the data layer, then we can use that to create a variety of Trigger extensions.

I listed a few Tags earlier that would be good to block from internal users or employees. In this case, we can bring in the IP address and check to see if it matches our regular expression.


12. Blocking – Internal – Cookie

Variables: Is Employee (First Party Cookie)

Use Case: Also from a previous blog post about filtering out employee traffic, if you can get employees to raise their hand and identify themselves as employees, you can set a cookie and use that later to help block certain Tags from firing. This implementation is helpful for companies where employees are often traveling or that do not have a static office IP address.


13. Blocking – Weekend Days

Variables: Day Of Week (Custom JavaScript)

Use Case: Remember that with Custom JavaScript, we can really do any calculation that we need. In this case, we’ll get the day of the week. I’m localizing this to the East Coast since that’s where we’re located. You’ll need to think about how you need your date to appear, in the visitor’s time zone, which will change, or in your business’s timezone.

You could theoretically use these Triggers to show weekday specific advertisements, or change Tags based on specific days. Imagine also pulling in the time of the day and being able to fire different Tags during business hours and when your office is closed.

function() {
	//Fill in your offset from GMT!
	// *********
	var offset = -4;
	// *********
	var current = new Date( new Date().getTime() + offset * 3600 * 1000);
	var daysOfWeek = new Array(7);
	daysOfWeek[0]=  "Sunday";
	daysOfWeek[1] = "Monday";
	daysOfWeek[2] = "Tuesday";
	daysOfWeek[3] = "Wednesday";
	daysOfWeek[4] = "Thursday";
	daysOfWeek[5] = "Friday";
	daysOfWeek[6] = "Saturday";

This list is meant to spark some creative ideas for how you can use Trigger exceptions! Feel free to use these variables or other custom JavaScript variables in creative ways.