You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

借助Google Tag Manager(JS)实现弹窗同会话不再重复弹出

问题解决:GTM弹窗会话内仅触发一次及相关Bug修复

问题背景

在Google Tag Manager(GTM)中配置了弹窗脚本,设置两个独立触发条件:30秒后通过自定义代码向data layer推送timer_elapsed事件触发、页面滚动50%时通过GTM Scroll Depth触发器触发。测试发现:

  • 弹窗在30秒显示并关闭后,滚动至页面50%位置会再次弹出
  • 二次弹出的弹窗无法关闭
  • {{DL - locale}}数据层变量定义的翻译功能失效
    需求:同一用户会话内,弹窗无论通过哪个触发条件显示后,不再重复出现。

问题根源

  1. 会话标记逻辑漏洞:原脚本仅在弹窗显示时标记会话状态,但未确保GTM多次触发脚本时能正确读取状态
  2. 事件绑定冲突:HTML中onclick="closePopup()"与JS中addEventListener重复绑定,二次触发时函数作用域异常导致关闭失效
  3. 初始状态未隐藏:弹窗默认未设置隐藏,导致脚本执行时显示判断逻辑出错
  4. 变量传递不稳定:GTM多次触发时,{{DL - locale}}变量未被正确注入到二次执行的脚本中

修改后的完整代码

JavaScript代码

// 检查弹窗是否已在当前会话中触发过
function hasPopupBeenTriggered() {
    return sessionStorage.getItem('popupTriggered') === 'true';
}

// 标记弹窗已触发
function markPopupAsTriggered() {
    sessionStorage.setItem('popupTriggered', 'true');
}

// 关闭弹窗
function closePopup() {
    const popupElement = document.getElementById('popup');
    if (popupElement) {
        popupElement.style.display = 'none';
        console.log("弹窗已关闭");
    }
}

// 翻译弹窗内容
function translatePopup(locale) {
    const translations = {
        'en': {
            'title': "End of year offer",
            'text': "Get <strong>500€ off</strong> on online bootcamps starting in 2023",
            'button': "Discover Online Bootcamps"
        },
        'fr': {
            'title': "Offre de fin d'année",
            'text': "Bénéficiez d'une <strong>réduction de 500€</strong> sur les bootcamps en ligne commençant en 2023",
            'button': "Découvrir les bootcamps en ligne"
        },
        // 添加其他语言翻译
    };

    const localeTranslations = translations[locale] || translations['en'];
    const titleEl = document.querySelector('#popup .split-right h2');
    const textEl = document.querySelector('#popup .split-right p');
    const buttonEl = document.querySelector('#popup .split-right button');
    
    if (titleEl) titleEl.innerHTML = localeTranslations.title;
    if (textEl) textEl.innerHTML = localeTranslations.text;
    if (buttonEl) buttonEl.textContent = localeTranslations.button;
}

// 初始化弹窗
function initPopup() {
    // 会话内已触发过,直接返回
    if (hasPopupBeenTriggered()) {
        console.log("弹窗已在当前会话中显示过,取消初始化");
        return;
    }

    const userLocale = "{{DL - locale}}";
    translatePopup(userLocale);

    const popupElement = document.getElementById('popup');
    if (!popupElement) return;

    // 标记弹窗已触发,避免后续触发条件再执行
    markPopupAsTriggered();
    
    // 显示弹窗
    popupElement.style.display = 'block';
    console.log("弹窗已显示");

    // 绑定关闭按钮事件(仅绑定一次)
    const closeButton = document.querySelector(".close-btn");
    if (closeButton && !closeButton.dataset.listenerAdded) {
        closeButton.addEventListener("click", closePopup);
        closeButton.dataset.listenerAdded = "true";
    }
}

// 执行初始化
initPopup();

HTML代码

<div id="popup" class="popup">
  <div class="popup-content">
    <span class="close-btn">&times;</span>
      <div class="split-left">
        <img src="#" alt="Popup image">
      </div>
      <div class="split-right">
        <h2>End of year offer</h2>
        <p>Get <strong>500€ off</strong> on online bootcamps starting in 2023</p>
        <a href="#"><button class="cta-popup">Discover Online Bootcamps</button></a>
      </div>
    </div>
  </div>

CSS代码

.cta-popup{
    border: 0;
    color: white;
    background-color: #670BFF;
    text-decoration: none;
    padding: 0.88rem 1.4rem;
    border-radius: 0.5rem;
    font-weight: 700;
    cursor: pointer;
}
.cta-popup:hover{
    background-color: #5809d9;
}
.split-left{
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.split-left > img{
    object-fit: cover;
    width: 100%;
    height: 100%;
}
.split-right{
    display: grid;
    align-content: center;
    width: 100%;
    height: 100%;
    padding: 2rem;
    grid-gap: 1rem;
}
.popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.3);
    z-index: 99999;
    /* 默认隐藏弹窗 */
    display: none;
}
.popup-content {
    position: absolute;
    display: flex;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    width: 500px;
    height: 500px;
    border-radius: 1rem;
    overflow: hidden;
}
.close-btn {
    position: absolute;
    right: 10px;
    top: 5px;
    font-size: 24px;
    cursor: pointer;
    z-index: 100000;
}

GTM配置注意事项

  1. 保留原有触发条件:继续使用30秒timer_elapsed事件触发和滚动50%触发两个触发器
  2. 验证数据层变量:确保{{DL - locale}}为GTM中正确配置的“数据层变量”,变量名与dataLayer中存储locale的键完全一致
  3. 标签配置:将修改后的脚本设置为GTM的“自定义HTML”标签,触发条件绑定两个触发器
  4. 避免重复注入:无需额外调整触发优先级,核心逻辑已通过sessionStorage确保会话内仅执行一次初始化

内容的提问来源于stack exchange,提问作者Édouard Bernard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:13:20