Don't have one? Create one ↗
← All courses
Lessons in this module

Lesson 13 of 15

Tab & Window Visibility

① Connect your GTM container

Paste your container ID to load it into this page. It only ever runs here.

Advanced: use a specific environment

A page can be open without being watched. The visitor switches to another tab, or clicks a different window, and your "time on page" quietly counts minutes nobody spent reading. Accurate engagement tracking means knowing when the page is actually visible and focused.

The browser exposes two signals for this: the Page Visibility API (visibilitychange, for tab switches) and window focus/blur (for clicking another window or app). GTM has no built-in trigger for either, so a Custom HTML listener covers both and pushes a single visibility_change event with the source and new state, which you catch with a Custom Event trigger.

Goal

Add a visibility listener, catch its visibility_change push with a Custom Event trigger, and capture the state in Data Layer Variables.

Build it in GTM

  1. Add the visibility listener

    GTM has no built-in trigger for this, so a small Custom HTML tag does the listening and pushes its own event. This one script covers two different signals:

    • Tab visibility — the Page Visibility API (visibilitychange / document.visibilityState) fires when the tab is switched away or the window is minimized.
    • Window focus — the window's focus and blur events fire when another window or app comes forward, even while this page stays on screen.
    1. Go to Tags → New and choose Custom HTML.
    2. Paste the script below into the HTML field. It pushes visibility_change with a visibility_source(tab or window) plus the current state.
    3. Set its firing trigger to All Pages, name it Listener - Visibility, and Save.
    <script>
      (function () {
        window.dataLayer = window.dataLayer || [];
        function pushVisibility(source) {
          window.dataLayer.push({
            event: 'visibility_change',
            visibility_source: source,                          // 'tab' or 'window'
            page_visible: document.visibilityState === 'visible', // tab on screen?
            window_focused: document.hasFocus()                  // window in front?
          });
        }
        // Tab visibility: switching tabs or minimizing the window.
        document.addEventListener('visibilitychange', function () {
          pushVisibility('tab');
        });
        // Window focus: clicking another window or app, even if this page
        // stays visible. Lets you test without opening a second tab.
        window.addEventListener('focus', function () { pushVisibility('window'); });
        window.addEventListener('blur',  function () { pushVisibility('window'); });
      })();
    </script>
  2. Create the Custom Event trigger

    1. Go to Triggers → New and choose Custom Event.
    2. Set Event name to visibility_change (it must match the event you pushed).
    3. Name it Event - visibility_change and Save.
  3. Capture the state in variables

    Add a Data Layer Variable (a User-Defined variable) for each field you pushed so your tag can report which signal changed and its new state:

    1. Go to Variables → New (under User-Defined Variables) and choose Data Layer Variable.
    2. Create DLV - visibility_source (name visibility_source), DLV - page_visible (name page_visible), and DLV - window_focused (name window_focused).
    3. Save each one.
  4. Attach a tag

    1. Go to Tags → New and choose Custom HTML with <script></script> (or your GA4 Event tag). Name it Custom HTML - Test.
    2. Under Triggering, add Event - visibility_change. If it's a GA4 tag, send DLV - visibility_source, DLV - page_visible, and DLV - window_focused as parameters. Then Save.

Debug in Tag Assistant

Copy this lesson's live URL and paste it into GTM Preview, that is the page Tag Assistant connects to. It has the clickable elements, so this page stays clean for reading.

  1. In your GTM, click Preview.
  2. Paste the live URL above and click Connect.
  3. Interact with the live page and watch your tag fire in Tag Assistant.

What you should expect to see

Each time you switch away and back, a visibility_change event appears in the timeline and dataLayer with visibility_source set to tab or window, the matching state, and your tag fires.

Verify your container

Built it? Export your container, Admin → Export Container, choose your workspace, then drop the JSON here to check it against this lesson.

Drop your container .json here

or browse · checked in your browser, nothing is uploaded

0 of 15 lessons complete
Was this lesson helpful?