How to Track Hover Events with Google Tag Manager


hover craft joy ride with dolphins

When visitors hover on your website, are they more likely to convert? Pick a hover target and add event tracking to find out.

If you want to listen for clicks or form submissions, Google Tag Manager has some seriously awesome automatic event tracking. It doesn’t cover hover events yet, though. So if you want to track a visitor hovering over a menu or pop-up window or other such thing-a-ma-jig, read on for a nifty bit of jQuery that will do the trick.

Step 1. Include the jQuery library.

If your page doesn’t have jQuery, or the jQuery library is only included in the page source after your Tag Manager container code, then the code I’m going to give you won’t work.

First things first: make sure your page source includes the jQuery library before Tag Manager.


Typically, jQuery and other scripts are included in the head element, while Tag Manager appears in the body element. Your page source won’t look exactly like the above. It’s the order that counts. The jQuery library has to come first.

Step 2. Identify the hover element.

Tag Manager needs some information like a unique element name, class, or id (or unique combination of attributes) so it doesn’t try to track everywhere the visitor hovers on the page. Right-click on the page where you want to track the hover event, and choose inspect element.


In this example, I’m going to track when a visitor hovers over some text that says “Cart (1 Item)”. That action produces a pop-up window showing the contents of the shopping cart.

I inspect the element by right-clicking on it, and see the text is contained in a div element with the class “wl-cart-summary”.

page source showing hover target element

Because the class “wl-cart-summary” is unique to this element, I can use it to write a jQuery selector. The selector will focus the hover tracking on the cart summary pop-up.

Step 3. Create a Custom HTML tag and enter jQuery.

Open Tag Manager and create a new tag of the Custom HTML tag type. Enter the script shown below, and customize the jQuery selector $(“div.wl-cart-summary”) to match your hover target.

This code targets the div element with the class “wl-cart-summary” and listens for when a visitor starts hovering and also for when she stops hovering. It doesn’t send an event to the data layer until the visitor stops hovering.

The code also calculates the amount of time a visitor hovered, so you can decide whether or not she hovered long enough to make it worth tracking an event. Here I push the event to the data layer if the visitor hovers for at least 1 second.

I send all of this info to the data layer because I’ll need it in the next step, when I write my GA event tag:

event: cart-hover
eventAction: {{cartText}} = a custom JavaScript macro (how many items in cart?)
eventLabel: {{url path}} = a default macro (what page was the visitor on?)
eventValue: seconds = a variable from my code (how long did she hover?)

And then I fire this tag on every page since it’s part of the top navigation. You could use a more selective rule if you don’t need to fire it everywhere.

Bonus tip: The eventAction doesn’t have to be a macro; it could just be a word or phrase. But I wanted to get fancy, since the text of this element can change. So I created a Custom JavaScript macro in Tag Manager called {{cartText}} to reflect the number of items in the cart when the visitor hovered.


The above macro cartText looks for an anchor with the class “cart-summary-trigger” inside an element with the class “wl-cart-summary” and returns the text of that anchor. (See the screen shot earlier from when I right-clicked to inspect the element.)

Step 4. Create a GA Event tag.

Finally, write a tag that will send an event to Google Analytics every time your cart-hover event gets pushed to the data layer.

Create a new tag in Tag Manager: tag type = Google Analytics and track type = Event.

Enter the information you pushed to the data layer in the Event Tracking Parameters, as shown below.


Then fire this tag with a new rule that says {{event}} equals cart-hover, or whatever event you pushed to the data layer.

If you haven’t already created the macros for eventAction, eventLabel, and eventValue, you’ll need to do that, too. Simply choose macro type Data Layer Variable and enter the same variable name that you pushed to the data layer, e.g. eventAction, etc. You’ll be able to re-use those macros with other events you might decide to track later.

Step 5. Update, Preview, Debug. Create New Version and Publish!

Test your tag to make sure it’s firing at the right times and capturing the right info. Then create a new version of your Tag Manager container and publish, and start collecting all that beautiful data!

How are you harnessing the power of Google Tag Manager? What events have you been able to track that aren’t covered yet by auto event tracking? Please share in the comments.

Dorcas Alexander is a Manager for the Analytics & Insight department. Her path to LunaMetrics followed stints in ad agency creative, math, and computer science. Dorcas has a master's degree in language and information technologies from Carnegie Mellon University, where she helped build precursors to a Universal Translator. One of the top-rated tournament Scrabble players in Pennsylvania, Dorcas has an insatiable drive to compete and win.

  • RYan

    Hi Dorcas,

    Thanks for the post. This is great.

    My event is firing, but the seconds is not working.

    Within Analytics I am seeing the eventAction as gtm.js.
    Any ideas?

  • RYan

    dont worry! my code mix up

    • Dorcas Alexander

      Glad the code is working for you. Thanks for reading!

  • Felix

    Hey! First of all: great post! realy!

    But how can I adapt your code so I can track when visitor clicked on a “Add to chart” Javascript button?

    That would be great help for me ^^

    Greetings from Germany

    • Dorcas Alexander

      Hi Felix, I actually track that, too! When a visitor clicks the “Check Out” button on my hovered page element, I fire an event tag. The rule that fires the tag has 3 conditions based on the following: (1) a tag with the built-in click listener, (2) a macro that reads the target of the link, and (3) a macro that reads the button text. The specific rule conditions are: (1) “event equals”, (2) “Auto Event URL matches RegEx /cart$” (i.e. the button target is the URL of my cart page), and (3) “button text contains Check Out”. I send a different event category (cart-hover-checkout) but the same action (cart text) and label (url path) as for my cart-hover event. Hope that helps!

  • Tuan Hoang

    Hi Dorcas ,

    (function (w, d, s, l, i) {
    w[l] = w[l] || []; w[l].push({ ‘gtm.start’:
    new Date().getTime(), event: ‘gtm.js’
    }); var f = d.getElementsByTagName(s)[0],
    j = d.createElement(s), dl = l != ‘dataLayer’ ? ‘&l=’ + l : ”; j.async = true; j.src =
    ‘//’ + i + dl; f.parentNode.insertBefore(j, f);
    })(window, document, ‘script’, ‘dataLayer’, ‘GTM-XXXXXXX’);.
    I’ve already had the GTM like above
    By following your article, i just need to call the script below to track the event.
    dataLayer.push({‘event’: ‘cart-hover’, ‘eventAction’: {{cartText}}, ‘eventLabel’: {{url path}}, ‘eventValue’: seconds});
    But i don’t understand in step 4. You said:Create a new tag in Tag Manager: tag type = Google Analytics and track type = Event.And enter the information you pushed to the data layer in the Event Tracking Parameters.
    How to create new tag in Tag Manager to track event. Please use your earlier example to continue the reply . Thanks a lot. I’m waiting for your response soonest.

    • Dorcas Alexander

      Hi Tuan, Sorry for the late reply. Make sure you are creating two new tags in Tag Manager: (1) the custom HTML tag with the entire script shown in Step 3 above, and (2) the Google Analytics Event tag. All the info you need to create the Event tag is in Step 4 above. Please let me know specifically which part you are unable to find, after you log in to your Google Tag Manager account, and I will see if I can help you some more.

  • Paul

    Hi Dorcas,

    Great post — thanks so much! We can fire the HTML tag with the conditional gtm.dom event to avoid requiring specific jQuery placement. In my specific case, jQuery must come after the GTM tag.

    Thanks again!

  • Hi Dorcas.

    Lovely article and just what i needed/wanted to find today. Thanks for sharing.

    Just one question. I am wanting to track hover time on individual items within a collection. There are about 20 items in this collection that all have the same div class. Everything I’ve tried based on your cartText script has returned either “undefined” in GA or pulled in all of the text from each of the 20 items in this grouping. Is it possible to pull in an image title or alt text using the img portion of the code? This page is not dynamic, but I don’t want to have to write a different tracking code for each element.

    • Dorcas Alexander

      Hi Sean, You can definitely return an image title or alt text. For example, if the current image has the class “state-in”, then to return the value of the attribute “data-caption” try using the following jQuery: var mytitle = $(“.state-in”).attr(“data-caption”); return mytitle; Hope that helps!

  • Hi Dorcas,

    thanks for the tutorial!
    I tried to capture the hover time over our hotline in the top right corner.

    Unfortunately I always get an error from your jQuery Script and I don’t know why:
    Uncaught TypeError: undefined is not a function

    This is what I got:

    $(document).ready(function() {

    // Hover over Hotline
    var startHover = $.now();

    startHover = $.now();
    var endHover = $.now();
    var msHovered = endHover – startHover;
    var seconds = msHovered/1000;
    if (seconds >= 1) {
    dataLayer.push({‘event’: ‘HoverHotline’, ‘hoverDuration’: seconds});


    I also checked the placement of the jQuery Script and the jQuery Version also has .hover as a function from what I could tell (

    Any idea what I’m missing?

    • Dorcas Alexander

      Hi Harry, Did you wrap your code with script and /script tags? It’s hard for me to diagnose further without seeing what else might be running on the page.

  • Harry

    Hi Dorcas,

    I used Skript Tags, I think they were removed from my comment. You can check my page, I left the code online.
    What’s bugging me is that Google Tag Manager obviously refactors the code into this:

    $(document).ready(function(){var b=$.now();$(“h3.head-hotline”).hover(function(){b=$.now()},function(){var a=$.now(),a=a-b,a=a/1E3;1<=a&&dataLayer.push({event:"HoverHotline",hoverDuration:a})})});

    • Dorcas Alexander

      Hi Harry, I checked one of my own pages where I have this code running successfully and it is also minified the same as yours. I looked at the site named in your email address and did not find this code in GTM there.

  • Harry

    Hi Dorcas,

    I found the solution – as usual it was obvious 🙂
    The jQuery Object wasn’t available as $. I simply had to rewrite the calling function:
    jQuery(document).ready(function($) {

    All working fine now, thx for your help!

  • Can you please explain the uses case of using the documentlayer type of event tracking using:

    dataLayer.push({‘event’: ‘Event BuilderSubmit’});

    verse the ga send method:

    ga(‘send’, ‘event’, ‘category’, ‘action’);

    • Dorcas Alexander

      Hi Mike, The ga send method is equivalent to using a tag in GTM, where the tag type is Universal Analytics and the track type is Event. Pushing an event to the data layer is useful for writing a rule to fire the GTM tag, because you can specify one of the rule’s conditions to be: event equals X (or, in your case: event equals Event BuilderSubmit). You would still need to enter the category and action in the GTM tag, or use a macro for category or action or both. Defining a macro allows you to grab the information from additional info that you write to the data layer with the event, or capture info that already exists on the page.

  • Thanks, Dorcas.
    Let me make sure I understand.



    dataLayer.push({‘event’: ‘Event BuilderSubmit’});

    The real difference is the datalayer method while I still have to set up a Macro, Trigger and a Tag in GTM it gives me the added flexibility to capture other bits of info from the page from the datalayer or element id.

    While the push method is quicker to code it only has the info that I write into the function call at the time.

    Is this correct?

    • Dorcas Alexander

      Hi Mike, Yes, there is more flexibility with Tag Manager as opposed to inline code for the reasons you stated specific to event tracking, as well as the additional overall advantages you have with Tag Manager – serving multiple pieces of code asynchronously, version control, and built-in modularity. You don’t have to use a macro in your GTM event tag to send the category and action, but you’ll make the best use of GTM’s modularity if you do use macros there.

Contact Us.

Follow Us



We'll get back to you
in ONE business day.
Our Locations
THE FOUNDRY [map] LunaMetrics

24 S. 18th Street
Suite 100

Pittsburgh, PA 15203


4115 N. Ravenswood
Suite 101
Chicago, IL 60613


2100 Manchester Rd.
Building C, Suite 1750
Wheaton, IL 60187