如何通过GTM跟踪无刷新JavaScript测验的用户答题行为?
问题描述
我有一个基于JavaScript的无刷新测验,核心特点如下:
- 点击「Next」按钮时无页面重载,仅通过JavaScript替换内容
- 每个问题的单选按钮ID均为
#answer1、#answer2等重复标识,无差异化元素 - 现有代码无法修改
现需通过GTM(Google Tag Manager)跟踪以下数据:
- 用户答题进度
- 各问题的访问次数
- 正确答案的数量
目前认为缺乏跟踪依据,请问是否可行?
以下是测验的完整代码:
HTML结构
<div class="quiz-container"> <div id="question-container"> <h3 id="question">Question</h3> <div id="answer-buttons"></div> </div> <button id="next-btn" class="btn hide">Next</button> <div id="result" class="hide"></div> <button id="restart-btn" class="btn hide">Restart</button> </div>
JavaScript代码
const questionContainer = document.getElementById("question-container"); const questionElement = document.getElementById("question"); const answerButtons = document.getElementById("answer-buttons"); const nextButton = document.getElementById("next-btn"); const restartButton = document.getElementById("restart-btn"); const resultDiv = document.getElementById("result"); let shuffledQuestions, currentQuestionIndex, score; const questions = [ { question: "What is 2 + 2 equal?", answers: [ { text: "4", correct: true }, { text: "22", correct: false }, { text: "222", correct: false }, { text: "2222", correct: false }, ], }, { question: "What does HTML mean?", answers: [ { text: "HyperText Markup Language", correct: true }, { text: "HighText Machine Language", correct: false }, { text: "HyperText Machine Language", correct: false }, { text: "HighText Markup Language", correct: false }, ], }, { question: "What property is used to change the background color?", answers: [ { text: "color", correct: false }, { text: "bgColor", correct: false }, { text: "background-color", correct: true }, { text: "background", correct: false }, ], }, { question: "What HTML element do we put JavaScript in?", answers: [ { text: "<js>", correct: false }, { text: "<javascript>", correct: false }, { text: "<script>", correct: true }, { text: "<scripting>", correct: false }, ], }, ]; startQuiz(); function startQuiz() { score = 0; questionContainer.style.display = "flex"; shuffledQuestions = questions.sort(() => Math.random() - 0.5); currentQuestionIndex = 0; nextButton.classList.remove("hide"); restartButton.classList.add("hide"); resultDiv.classList.add("hide"); setNextQuestion(); } function setNextQuestion() { resetState(); showQuestion(shuffledQuestions[currentQuestionIndex]); } function showQuestion(question) { questionElement.innerText = question.question; question.answers.forEach((answer, index) => { const inputGroup = document.createElement("div"); inputGroup.classList.add("input-group"); const radio = document.createElement("input"); radio.type = "radio"; radio.id = "answer" + index; radio.name = "answer"; radio.value = index; const label = document.createElement("label"); label.htmlFor = "answer" + index; label.innerText = answer.text; inputGroup.appendChild(radio); inputGroup.appendChild(label); answerButtons.appendChild(inputGroup); }); } function resetState() { while (answerButtons.firstChild) { answerButtons.removeChild(answerButtons.firstChild); } } nextButton.addEventListener("click", () => { const answerIndex = Array.from( answerButtons.querySelectorAll("input") ).findIndex((radio) => radio.checked); if (answerIndex !== -1) { if (shuffledQuestions[currentQuestionIndex].answers[answerIndex].correct) { score++; } currentQuestionIndex++; if (shuffledQuestions.length > currentQuestionIndex) { setNextQuestion(); } else { endQuiz(); } } else { alert("select an aswer"); } }); restartButton.addEventListener("click", startQuiz); function endQuiz() { questionContainer.style.display = "none"; nextButton.classList.add("hide"); restartButton.classList.remove("hide"); resultDiv.classList.remove("hide"); resultDiv.innerText = `score : ${score} / ${shuffledQuestions.length}`; }
可行方案:无需修改现有代码的GTM跟踪实现
完全可以实现,核心思路是通过GTM的自定义事件监听、DOM元素提取和全局变量捕获来获取所需数据,具体方案如下:
1. 跟踪答题进度与问题访问次数
实现逻辑
每次问题切换时(包括初始加载、点击Next后加载新问题),捕获当前问题文本,结合用户会话统计访问次数,同时记录当前答题进度。
GTM配置步骤
- 创建自定义触发器:
- 选择「DOM Ready」触发器,触发条件设置为「元素ID」等于
question,且「元素可见性」为「可见」(每次问题切换都会更新#question的文本)。 - 补充「点击触发器」,触发条件为「元素ID」等于
next-btn,捕捉用户点击Next后的问题切换。
- 选择「DOM Ready」触发器,触发条件设置为「元素ID」等于
- 创建自定义JavaScript变量:
编写脚本提取当前问题文本:function() { return document.getElementById('question').innerText.trim(); } - 创建分析标签:
发送事件到分析工具(如GA4),事件参数包含:event_name:quiz_question_viewquestion_text: 上述自定义变量的值progress: 当前问题序号(可通过统计会话内quiz_question_view事件的次数得到,或用GTM会话变量计数)
2. 跟踪正确答案数量
实现逻辑
用户点击Next时,通过DOM提取选中的选项文本,结合全局变量score或原始问题数据判断是否正确。
GTM配置步骤
方案A:捕获全局score变量(高效)
- 创建自定义JavaScript变量:
直接读取全局score值:function() { return window.score || 0; } - 创建触发器:
选择「点击触发器」,触发条件为「元素ID」等于next-btn,且点击元素父级包含answer-buttons(确保是答题后的Next点击)。 - 创建分析标签:
每次点击Next时发送事件quiz_answer_submitted,参数包含:current_score: 上述score变量的值question_text: 当前问题文本(同步骤1的变量)selected_answer: 选中的选项文本(通过以下脚本提取)function() { const checkedRadio = document.querySelector('#answer-buttons input[type="radio"]:checked'); if (checkedRadio) { return document.querySelector(`label[for="${checkedRadio.id}"]`).innerText.trim(); } return null; }
方案B:无全局变量时的判断(兼容复杂场景)
如果全局变量不可用,可通过对比问题文本和选中选项,匹配原始问题数据中的正确答案:
- 创建自定义变量存储原始问题数据(复制JS中的
questions数组):function() { return [ { question: "What is 2 + 2 equal?", answers: [{ text: "4", correct: true }, ...] }, // 复制所有问题数据 ]; } - 编写脚本判断选中答案是否正确:
function() { const currentQuestion = document.getElementById('question').innerText.trim(); const checkedRadio = document.querySelector('#answer-buttons input[type="radio"]:checked'); if (!checkedRadio) return false; const selectedAnswer = document.querySelector(`label[for="${checkedRadio.id}"]`).innerText.trim(); const questions = {{原始问题数据变量}}; const targetQuestion = questions.find(q => q.question === currentQuestion); return targetQuestion ? targetQuestion.answers.find(a => a.text === selectedAnswer)?.correct : false; } - 发送事件时携带
is_correct参数,后续在分析工具中累计正确次数。
3. 跟踪测验重启与完成事件
- 测验完成:创建「DOM Ready」触发器,触发条件为「元素ID」等于
result且「元素可见性」为「可见」,发送事件quiz_completed,参数包含最终得分(提取#result的文本)。 - 测验重启:创建「点击触发器」,触发条件为「元素ID」等于
restart-btn,发送事件quiz_restarted。
内容的提问来源于stack exchange,提问作者blogob
相关产品推荐
相关产品推荐

