Skip to content

Make the page react to the quiz

Goal: the page around the quiz follows it: a colour per quiz page, the header hidden on the result page, a track that starts once the shopper is in.

Uses: Storefront JS API, page.viewed, quiz.started, quiz.finished, quiz.closed. Nothing to install; no API key. Events fire on the Plus and Enterprise plans.

page.viewed fires when a page lands (the first page at mount, every later one once the server confirmed it). Put its page_key on the root element and let CSS do the rest:

<script>
window.octaneai = window.octaneai || [];
window.octaneai.push(function (octaneai) {
octaneai.on('page.viewed', function (event) {
var page = event.data.object;
var root = document.documentElement;
root.setAttribute('data-quiz-page', page.page_key);
root.setAttribute('data-quiz-page-index', String(page.page_index));
root.classList.toggle('quiz-done', page.terminal_page !== null);
});
octaneai.on('quiz.closed', function () {
document.documentElement.removeAttribute('data-quiz-page');
});
});
</script>
<style>
html[data-quiz-page] body { transition: background-color 400ms; }
html[data-quiz-page="skin"] body { background-color: #f4efe6; }
html[data-quiz-page="goals"] body { background-color: #e6eef4; }
html.quiz-done body { background-color: #111; color: #fff; }
html.quiz-done .site-header { display: none; }
</style>

page_key is the key the page has in the editor. terminal_page is the page key when this landing completed the quiz, otherwise null; quiz.finished fires right after that landing, so either works for “the shopper is on the result”.

Browsers refuse audio.play() without a user gesture, and the first page.viewed fires at mount before the shopper touched anything. quiz.started fires when the first answer is saved, which is always after a click, so start there:

window.octaneai = window.octaneai || [];
window.octaneai.push(function (octaneai) {
var track = document.getElementById('quiz-music');
octaneai.on('quiz.started', function () {
if (track) track.play().catch(function () {});
});
octaneai.on('quiz.finished', function () {
if (track) track.pause();
});
});
  • A listener that throws is logged as [OctaneAI] listener for page.viewed threw and never breaks the quiz; there is nothing to catch on your side.
  • play() still rejects when the browser’s autoplay policy blocks it (a shopper who navigated here without interacting with the site); the .catch above keeps that silent.
  • A page-link button’s jump is client-side and is not reported; the next confirmed page names the last confirmed page as previous_page_key.
  • quiz.closed fires only for a fullscreen quiz (its X, or octaneai.close()); an inline quiz has no close.
  • Two quizzes on one page both fire page.viewed; pass { quizId } to on() to follow one of them.
  • Restyling the quiz itself this way does not work: the quiz renders inside a shadow root and its theme variables are set inside it, so host CSS does not reach in.
  • Set localStorage['octaneai:debug'] = '1' in the console to see every event as it fires.