Skip to main content
The LanderLab Quiz Events API publishes the lifecycle of your quiz so you can interact with it using custom JavaScript. This is particularly useful if you want to implement your own granular tracking or if you want to interact with your quiz data client-side.

Introduction

The Events API allows you to listen to different lifecycle events of your quiz and execute custom code when these events occur. Here’s a basic example:
window.addEventListener('ll-quiz-init', (event) => {
    console.log('ll-quiz init:', event.detail.quizId);
    const llQuizApi = event.detail.llQuizApi;
    
    // Use llQuizApi here
});
where ll-quiz-init is the Event Name of the lifecycle event.

Events Overview

Your quiz emits the following events per lifecycle event:
Event NameLifecycle EventData Passed
ll-quiz-initWhen the quiz loads initially and is bound to the DOMquizId, llQuizApi
ll-quiz-submitWhen the quiz gets submittedquizId, stepId, stepName, fields, fieldsSimple, llQuizApi, response
ll-quiz-step-viewWhen a step is visitedquizId, stepId, stepName, fields, fieldsSimple, llQuizApi
ll-quiz-step-leaveWhen navigating away from a stepquizId, stepName, llQuizApi
ll-quiz-exitWhen the tab/window in which the quiz lives gets closedquizId, llQuizApi
ll-quiz-button-clickWhen a button block is clicked (DefaultButton, Continue, Previous)quizId, blockId, blockName, stepId, stepName, llQuizApi
ll-quiz-input-clickWhen a Multiple Choice or Image Choice option is clickedquizId, blockId, blockName, stepId, stepName, optionId, optionValue, optionLabel, llQuizApi

ll-quiz-init Event

When: When the quiz loads initially and is bound to the DOM. Event Detail:
  • quizId (string): The unique identifier of the quiz
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-init', (event) => {
    const { quizId, llQuizApi } = event.detail;
    console.log('Quiz initialized:', quizId);
    
    // Access the LlQuiz API
    const currentStepId = llQuizApi.getCurrentStepID();
    const allBlocks = llQuizApi.getBlocks();
});

ll-quiz-submit Event

When: When the quiz gets submitted (typically when the submit button is clicked and the form is successfully submitted). Event Detail:
  • quizId (string): The unique identifier of the quiz
  • stepId (string): The step ID where submission occurred
  • stepName (string): The step name where submission occurred
  • fields (Field[]): Array of field objects with detailed information (see Fields Structure below)
  • fieldsSimple (FieldsSimple): Key-value object with label as key and value as string (see FieldsSimple Structure below)
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
  • response (any): The API response from the submission endpoint. Can be:
    • The parsed JSON response if the API returns JSON
    • The Response object if it’s not JSON
    • null if the API call failed
Example:
window.addEventListener('ll-quiz-submit', (event) => {
    const { quizId, stepId, stepName, fields, fieldsSimple, llQuizApi, response } = event.detail;
    console.log('Quiz submitted:', quizId);
    console.log('Submitted from step:', stepName);
    console.log('Submitted data:', fieldsSimple);
    console.log('API Response:', response);
    
    // Send to your analytics platform
    if (window.gtag) {
        window.gtag('event', 'quiz_submit', {
            'quiz_id': quizId,
            'step_id': stepId,
            'step_name': stepName
        });
    }
});

ll-quiz-step-view Event

When: When a step is visited (whenever the user navigates to a new step). Event Detail:
  • quizId (string): The unique identifier of the quiz
  • stepId (string): The step ID that was viewed
  • stepName (string): The step name that was viewed
  • fields (Field[]): Array of field objects from the current step (see Fields Structure below)
  • fieldsSimple (FieldsSimple): Key-value object with label as key and value as string for the current step (see FieldsSimple Structure below)
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-step-view', (event) => {
    const { quizId, stepId, stepName, fields, fieldsSimple, llQuizApi } = event.detail;
    console.log('Quiz:', quizId);
    console.log('Step viewed:', stepName);
    console.log('Current step data:', fieldsSimple);
    
    // Track step view
    if (window.dataLayer) {
        window.dataLayer.push({
            'event': 'll_quiz_step_view',
            'quiz_id': quizId,
            'step_id': stepId,
            'step_name': stepName
        });
    }
});

ll-quiz-step-leave Event

When: When navigating away from a step (before the next step is shown). Event Detail:
  • quizId (string): The unique identifier of the quiz
  • stepName (string): The step name being left
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-step-leave', (event) => {
    const { quizId, stepName, llQuizApi } = event.detail;
    console.log('Quiz:', quizId);
    console.log('Leaving step:', stepName);
    
    // Get current step information before leaving
    const currentStepId = llQuizApi.getCurrentStepID();
    console.log('Current step ID:', currentStepId);
});

ll-quiz-exit Event

When: When the tab/window in which the quiz lives gets closed. This event is based on the native pagehide event, which, unfortunately, is not entirely reliable. The event may not fire in all scenarios (e.g., force quit, browser crash, or certain mobile browser behaviors). Don’t rely on it for critical operations. Event Detail:
  • quizId (string): The unique identifier of the quiz
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-exit', (event) => {
    const { quizId, llQuizApi } = event.detail;
    console.log('Quiz exited:', quizId);
    
    // Track exit event (e.g., for analytics)
    if (window.gtag) {
        window.gtag('event', 'quiz_exit', {
            'quiz_id': quizId
        });
    }
    
    // Note: This event may not fire reliably in all scenarios
    // Don't rely on it for critical operations
});

ll-quiz-button-click Event

When: When a button block is clicked. This includes DefaultButton, Continue, Previous, and Submit button blocks. Event Detail:
  • quizId (string): The unique identifier of the quiz
  • blockId (string): The unique identifier of the button block that was clicked
  • blockName (string): The name property of the button block
  • stepId (string): The step ID where the button is located
  • stepName (string): The step name where the button is located
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-button-click', (event) => {
    const { quizId, blockId, blockName, stepId, stepName, llQuizApi } = event.detail;
    console.log('Button clicked:', blockName);
    console.log('In step:', stepName);
    
    // Track button clicks for analytics
    if (window.gtag) {
        window.gtag('event', 'button_click', {
            'quiz_id': quizId,
            'block_id': blockId,
            'block_name': blockName,
            'step_id': stepId,
            'step_name': stepName
        });
    }
    
    // Perform custom logic based on button type
    if (blockName === 'submit-button') {
        console.log('Submit button was clicked!');
    }
});

ll-quiz-input-click Event

When: When a Multiple Choice option or Image Choice option is clicked. Event Detail:
  • quizId (string): The unique identifier of the quiz
  • blockId (string): The unique identifier of the block where the option was clicked
  • blockName (string): The name property of the block
  • stepId (string): The step ID where the block is located
  • stepName (string): The step name where the block is located
  • optionId (string): The unique identifier of the clicked option
  • optionValue (string): The value of the clicked option
  • optionLabel (string): The label of the clicked option
  • llQuizApi (LlQuizApi): The LlQuiz API instance for interacting with the quiz
Example:
window.addEventListener('ll-quiz-input-click', (event) => {
    const { quizId, blockId, blockName, stepId, stepName, optionId, optionValue, optionLabel, llQuizApi } = event.detail;
    console.log('Option clicked:', optionLabel);
    console.log('In block:', blockName);
    console.log('In step:', stepName);
    
    // Track option clicks for analytics
    if (window.gtag) {
        window.gtag('event', 'option_click', {
            'quiz_id': quizId,
            'block_id': blockId,
            'block_name': blockName,
            'step_id': stepId,
            'step_name': stepName,
            'option_id': optionId,
            'option_value': optionValue,
            'option_label': optionLabel
        });
    }
    
    // Perform custom logic based on option selection
    if (optionValue === 'premium-plan') {
        console.log('Premium plan selected!');
    }
});

Understanding fields and fieldsSimple

fields and fieldsSimple contain all information from your quiz in different structures. Quick Overview:
  • fieldsSimple: A key-value object where keys are field labels and values are user inputs as strings
  • fields: An array of detailed field objects with complete metadata (id, label, value, key, stepId, stepName)
Quick Example:
fieldsSimple: {
    "Choose your housing type": "Apartment",
    "Email": "[email protected]",
    "Consent": "true",
},

fields: [
    {
        id: "text-field-123",
        label: "Please enter your name",
        value: "John Doe",
        key: "text-field-123",
        stepId: "step-1",
        stepName: "start"
    }
]

Using LlQuiz API in Events

All events provide access to the llQuizApi instance, which allows you to interact with your quiz programmatically. Available Methods:
  • llQuizApi.getCurrentStepID() – Returns the current step ID (e.g., “step-1”)
  • llQuizApi.getCurrentStepName() – Returns the current step name (e.g., “start”)
  • llQuizApi.getBlocks() – Returns all blocks in the quiz
  • llQuizApi.getBlockByID(blockId) – Returns a specific block by its ID
  • llQuizApi.getBlockByName(blockName) – Returns a block by its name property (first match)
  • llQuizApi.getBlocksByStepID(stepId) – Returns all blocks in a specific step
  • llQuizApi.getBlocksByStepName(stepName) – Returns all blocks in a specific step
Block Methods: Most blocks support:
  • block.getValue() – Get the current value of the block
  • block.setValue(value) – Set the value of the block
  • block.reset() – Reset the block to its initial state
Example:
window.addEventListener('ll-quiz-step-view', (event) => {
    const { llQuizApi } = event.detail;
    
    // Get all blocks in current step
    const currentStepId = llQuizApi.getCurrentStepID();
    const stepBlocks = llQuizApi.getBlocksByStepID(currentStepId);
    
    // Interact with blocks
    stepBlocks.forEach(block => {
        if (block.blockType === 'text-field') {
            const value = block.getValue();
            console.log(`${block.blockID}: ${value}`);
        }
    });
});

Complete Example

Here’s a complete example showing how to use all quiz events together:
window.addEventListener('ll-quiz-init', (event) => {
    const { quizId, llQuizApi } = event.detail;
    console.log('Quiz initialized:', quizId);
});

window.addEventListener('ll-quiz-step-view', (event) => {
    const { quizId, stepId, stepName, fieldsSimple, llQuizApi } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log(`Viewing step: ${stepName} (${stepId})`);
    console.log('Step data:', fieldsSimple);
});

window.addEventListener('ll-quiz-step-leave', (event) => {
    const { quizId, stepName } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log(`Leaving step: ${stepName}`);
});

window.addEventListener('ll-quiz-submit', (event) => {
    const { quizId, stepId, stepName, fields, fieldsSimple, response } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log(`Quiz submitted from step: ${stepName} (${stepId})`);
    console.log('All quiz data:', fieldsSimple);
    console.log('API response:', response);
    
    // Example: Send to analytics
    if (window.gtag) {
        window.gtag('event', 'conversion', {
            'send_to': 'AW-CONVERSION_ID/CONVERSION_LABEL',
            'value': 1.0,
            'currency': 'USD'
        });
    }
});

window.addEventListener('ll-quiz-exit', (event) => {
    const { quizId, llQuizApi } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log('Quiz exited (tab/window closed)');
    
    // Example: Track exit event
    if (window.gtag) {
        window.gtag('event', 'quiz_exit', {
            'quiz_id': quizId
        });
    }
    
    // Note: This event is based on pagehide and may not fire reliably
    // Don't rely on it for critical operations
});

window.addEventListener('ll-quiz-button-click', (event) => {
    const { quizId, blockId, blockName, stepId, stepName, llQuizApi } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log(`Button clicked: ${blockName} (${blockId})`);
    console.log(`In step: ${stepName} (${stepId})`);
    
    // Example: Track button clicks
    if (window.gtag) {
        window.gtag('event', 'button_click', {
            'quiz_id': quizId,
            'block_id': blockId,
            'block_name': blockName,
            'step_id': stepId,
            'step_name': stepName
        });
    }
});

window.addEventListener('ll-quiz-input-click', (event) => {
    const { quizId, blockId, blockName, stepId, stepName, optionId, optionValue, optionLabel, llQuizApi } = event.detail;
    console.log(`Quiz: ${quizId}`);
    console.log(`Option clicked: ${optionLabel} (${optionId})`);
    console.log(`In block: ${blockName} (${blockId})`);
    console.log(`In step: ${stepName} (${stepId})`);
    
    // Example: Track option clicks
    if (window.gtag) {
        window.gtag('event', 'option_click', {
            'quiz_id': quizId,
            'block_id': blockId,
            'block_name': blockName,
            'step_id': stepId,
            'step_name': stepName,
            'option_id': optionId,
            'option_value': optionValue,
            'option_label': optionLabel
        });
    }
});