> ## Documentation Index
> Fetch the complete documentation index at: https://docs.landerlab.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Quiz Events API for Tracking and Automation

> Use Quiz Events API to track user actions, monitor quiz lifecycle events, and trigger custom logic for advanced funnel optimization.

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:

```text theme={null}
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 Name           | Lifecycle Event                                                    | Data Passed                                                                                 |
| :------------------- | :----------------------------------------------------------------- | :------------------------------------------------------------------------------------------ |
| ll-quiz-init         | When the quiz loads initially and is bound to the DOM              | quizId, llQuizApi                                                                           |
| ll-quiz-submit       | When the quiz gets submitted                                       | quizId, stepId, stepName, fields, fieldsSimple, llQuizApi, response                         |
| ll-quiz-step-view    | When a step is visited                                             | quizId, stepId, stepName, fields, fieldsSimple, llQuizApi                                   |
| ll-quiz-step-leave   | When navigating away from a step                                   | quizId, stepName, llQuizApi                                                                 |
| ll-quiz-exit         | When the tab/window in which the quiz lives gets closed            | quizId, llQuizApi                                                                           |
| ll-quiz-button-click | When a button block is clicked (DefaultButton, Continue, Previous) | quizId, blockId, blockName, stepId, stepName, llQuizApi                                     |
| ll-quiz-input-click  | When a Multiple Choice or Image Choice option is clicked           | quizId, 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:**

```text theme={null}
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:**

```text theme={null}
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:**

```text theme={null}
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:**

```text theme={null}
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:**

```text theme={null}
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:**

```text theme={null}
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:**

```text theme={null}
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:**

```json theme={null}
fieldsSimple: {
    "Choose your housing type": "Apartment",
    "Email": "email@example.com",
    "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:**

```text theme={null}
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:

```text theme={null}
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
        });
    }
});
```
