Skip to content

Auto-advance an in-store kiosk quiz

Goal: a quiz on a shop-floor tablet never sits on a half-answered page: after a few idle seconds it moves on, skips a question nobody answered, and when a finished quiz is left alone it goes back to the start for the next person.

Uses: Storefront JS API, navigate('next' | 'skip'), page.rejected, quiz.finished, error. Nothing to install; no API key. The methods work on every plan; the events fire on the Plus and Enterprise plans.

Advance on idle, skip what was not answered

Section titled “Advance on idle, skip what was not answered”

Any touch, click or key resets the idle clock. When it runs out, navigate('next') submits the page the way the Next button does. If the page has a required question nobody answered, that next is refused and page.rejected fires; the handler answers with navigate('skip'), which moves on without saving the page.

<script>
window.octaneai = window.octaneai || [];
window.octaneai.push(function (octaneai) {
var IDLE_MS = 15000;
var RESET_MS = 60000;
var timer = null;
var finished = false;
var stuckOn = null;
function arm() {
clearTimeout(timer);
timer = setTimeout(function () {
var state = octaneai.getState();
if (finished || !state || state.page_key === stuckOn) { location.reload(); return; }
stuckOn = state.page_key; // a page.viewed clears it: the navigate moved on
octaneai.navigate('next');
arm(); // the next idle round runs even when nothing moved
}, finished ? RESET_MS : IDLE_MS);
}
['pointerdown', 'keydown', 'touchstart'].forEach(function (name) {
document.addEventListener(name, arm, { capture: true, passive: true });
});
octaneai.on('page.rejected', function () {
octaneai.navigate('skip');
});
octaneai.on('page.viewed', function () {
stuckOn = null;
arm();
});
octaneai.on('quiz.finished', function () {
finished = true;
arm();
});
octaneai.on('error', function (event) {
if (event.data.object.code === 'navigate_failed') location.reload();
});
});
</script>

page.rejected fires for a refused next whether your code or the shopper asked for it, so a shopper who taps Next on an unanswered required question is also skipped forward; raise IDLE_MS or gate the skip on your own idle flag if that is unwanted.

stuckOn is the second way out: when an idle next leaves the page where it was (the last page of a quiz that did not finish, a page the quiz will not leave), the next idle round reloads instead of asking again.

There is no restart on the API: a session cannot be reset in place. location.reload() mounts the quiz again and starts a new session, which is what the kiosk needs between two people. Each reload is a new session in the quiz’s analytics and on the plan’s session count.

  • navigate('skip') on a page that cannot be skipped (the result page, a page the quiz’s rules hold) is refused by the server and reported as error with code: 'navigate_failed'; the handler above reloads rather than looping.
  • navigate() before the quiz mounted logs [OctaneAI] no quiz on this page yet and does nothing; the first page.viewed arms the timer, so nothing runs before that.
  • A session that skipped every question lands on the result page without finishing: terminal_page stays null and quiz.finished never fires, so finished never turns true on a kiosk nobody touched. That is what stuckOn is for; the reload starts the next session.
  • navigate('next') goes through the page’s validation; an answered page is saved and question.answered fires for it, an unanswered one is skipped as above.
  • skip saves nothing and fires no question.answered; an answer typed but not submitted on that page is dropped.
  • The shopper’s touches on the quiz reach document (the quiz’s shadow root does not stop them), so the idle clock resets on them too.