> ## 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.

# Die Quiz-Events-API für Tracking und Automatisierung nutzen

> Reagieren Sie auf Ereignisse in Ihrem Quiz: Es wird geladen, ein Schritt wird angezeigt, eine Antwort ändert sich, die Validierung schlägt fehl, der Besucher sendet ab.

Ihr Quiz meldet Ereignisse als Browser-Events auf `window`. Hören Sie sie ab, um Verhalten in Ihrer Analyse zu erfassen, auf Antworten zu reagieren oder eigenen Code zum richtigen Zeitpunkt auszuführen.

```javascript theme={null}
window.addEventListener('ll-quiz-step-view', (event) => {
  console.log('Visitor is on step', event.detail.stepName);
});
```

Jedes Event legt seine Daten in `event.detail` ab. Zwei Angaben sind immer enthalten:

* `quizId`: welches Quiz das Event ausgelöst hat
* `llQuizApi`: die [Quiz-API](/de/features/quizzes/api/reference), sodass Sie das Quiz direkt im Listener auslesen oder ändern können

<Note>
  `ll-quiz-init` wird ausgelöst, sobald das Quiz bereit ist – das kann vor der Ausführung Ihres Skripts sein. Kein Problem: Ein spät registrierter Listener erhält `ll-quiz-init` trotzdem. Alle anderen Events werden durch Besucheraktionen ausgelöst, also nachdem Ihr Skript bereitsteht.
</Note>

## Events auf einen Blick

| Event                           | Wird ausgelöst, wenn                         | Nützliche Daten                                 |
| :------------------------------ | :------------------------------------------- | :---------------------------------------------- |
| `ll-quiz-init`                  | Das Quiz bereit ist                          | `llQuizApi`                                     |
| `ll-quiz-step-view`             | Ein Schritt angezeigt wird                   | `stepName`, `fields`                            |
| `ll-quiz-step-leave`            | Der Besucher einen Schritt verlässt          | `stepName`                                      |
| `ll-quiz-value-change`          | Eine Antwort übernommen wird                 | `blockName`, `value`, `previousValue`, `source` |
| `ll-quiz-input-click`           | Eine Auswahloption angeklickt wird           | `blockName`, `optionLabel`, `optionValue`       |
| `ll-quiz-button-click`          | Eine Schaltfläche angeklickt wird            | `blockName`                                     |
| `ll-quiz-validation-error`      | Das Verlassen eines Schritts blockiert wurde | `errors`, `source`                              |
| `ll-quiz-google-address-select` | Eine Adresse ausgewählt wird                 | `address`                                       |
| `ll-quiz-submit`                | Das Quiz abgesendet wurde                    | `fields`, `fieldsSimple`, `response`            |
| `ll-quiz-exit`                  | Der Tab geschlossen wird                     |                                                 |

## ll-quiz-init

Wird ausgelöst, sobald das Quiz auf der Seite und bereit ist. Hier holen Sie sich `llQuizApi`, befüllen Werte vor oder richten Dinge ein.

<ResponseField name="quizId" type="string" />

<ResponseField name="llQuizApi" type="LlQuizApi">
  Die Quiz-API für dieses Quiz
</ResponseField>

```javascript theme={null}
window.addEventListener('ll-quiz-init', (event) => {
  const quiz = event.detail.llQuizApi;
  quiz.getBlock('source').setValue('landing-page-a');
});
```

## ll-quiz-step-view

Wird jedes Mal ausgelöst, wenn ein Schritt angezeigt wird – auch beim ersten Schritt nach dem Laden und wenn der Besucher zurückgeht.

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

<ResponseField name="fields" type="Field[]">
  Bisher gegebene Antworten, siehe [fields und fieldsSimple](#fields-and-fieldssimple)
</ResponseField>

<ResponseField name="fieldsSimple" type="object">
  Dieselben Antworten als Label → Wert
</ResponseField>

```javascript theme={null}
window.addEventListener('ll-quiz-step-view', (event) => {
  const { stepName, quizId } = event.detail;
  window.dataLayer?.push({ event: 'quiz_step', quiz: quizId, step: stepName });
});
```

## ll-quiz-step-leave

Wird ausgelöst, wenn der Besucher einen Schritt verlässt – vor dem nächsten `ll-quiz-step-view`. Nutzen Sie es, um die Verweildauer eines Schritts zu messen oder einen Entwurf zu speichern.

<ResponseField name="stepName" type="string" />

```javascript theme={null}
let shownAt = Date.now();

window.addEventListener('ll-quiz-step-view', () => {
  shownAt = Date.now();
});

window.addEventListener('ll-quiz-step-leave', (event) => {
  const seconds = Math.round((Date.now() - shownAt) / 1000);
  window.dataLayer?.push({ event: 'quiz_step_time', step: event.detail.stepName, seconds });
});
```

## ll-quiz-value-change

Wird ausgelöst, wenn eine Antwort übernommen wird. Getippte Felder (Text, E-Mail, Telefon, Zahl, Textarea, Datum, Geburtsdatum, Postleitzahl, Adresse, OTP) übernehmen den Wert, wenn der Besucher das Feld oder den Schritt verlässt – Sie erhalten also ein Event pro Antwort, nicht pro Tastenanschlag. Alle anderen Eingaben und jeder über die API gesetzte Wert werden sofort übernommen.

<ResponseField name="blockId" type="string" />

<ResponseField name="blockName" type="string">
  Der im Builder vergebene Name des Blocks
</ResponseField>

<ResponseField name="blockType" type="string">
  Zum Beispiel `text-field` oder `multiple-choice`
</ResponseField>

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

<ResponseField name="value" type="string">
  Die neue Antwort, im selben Format wie `Field.value`
</ResponseField>

<ResponseField name="previousValue" type="string">
  Die zuletzt gemeldete Antwort oder der Wert, mit dem das Quiz geladen wurde
</ResponseField>

<ResponseField name="source" type="'user' | 'api' | 'system'">
  `user`: der Besucher. `api`: Ihr Skript über die Quiz-API. `system`: das Quiz selbst, etwa beim Leeren der Antworten nach dem Absenden
</ResponseField>

Hat sich der Wert nicht geändert, wird nichts ausgelöst. Werte, die beim Laden des Quiz bereits vorhanden sind (Standardwerte, URL-Parameter, wiederhergestellte Antworten), bilden den Ausgangspunkt und lösen nichts aus; sie stehen in `fields` bei `ll-quiz-step-view`.

```javascript theme={null}
window.addEventListener('ll-quiz-value-change', (event) => {
  const { blockName, value, source } = event.detail;
  if (source !== 'user') return; // skript- und systemgesteuerte Änderungen ignorieren

  window.dataLayer?.push({ event: 'quiz_answer', field: blockName, value });
});
```

## ll-quiz-input-click

Wird ausgelöst, wenn der Besucher eine Option eines Multiple-Choice- oder Bildauswahl-Blocks anklickt. Wird beim selben Klick vor `ll-quiz-value-change` ausgelöst.

<ResponseField name="blockId" type="string" />

<ResponseField name="blockName" type="string" />

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

<ResponseField name="optionId" type="string" />

<ResponseField name="optionValue" type="string">
  Der Wert der Option, wie er in der Antwort gespeichert wird
</ResponseField>

<ResponseField name="optionLabel" type="string">
  Der Text, den der Besucher gesehen hat
</ResponseField>

```javascript theme={null}
window.addEventListener('ll-quiz-input-click', (event) => {
  const { blockName, optionLabel, optionValue, llQuizApi } = event.detail;

  window.dataLayer?.push({ event: 'quiz_option', field: blockName, option: optionLabel });

  // Unter der Tarifauswahl einen Hinweis für eine Option anzeigen
  if (blockName === 'plan') {
    const hint = llQuizApi.getBlock('planHint');
    optionValue === 'enterprise' ? hint.visibility.show() : hint.visibility.hide();
  }
});
```

## ll-quiz-button-click

Wird ausgelöst, wenn ein Continue-, Previous-, Submit- oder Button-Block angeklickt wird – vor jeder Validierung. Es wird auch dann ausgelöst, wenn der Klick am Ende blockiert wird; es zählt also Versuche, keine Erfolge.

<ResponseField name="blockId" type="string" />

<ResponseField name="blockName" type="string" />

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

```javascript theme={null}
window.addEventListener('ll-quiz-button-click', (event) => {
  const { blockName, stepName } = event.detail;
  window.dataLayer?.push({ event: 'quiz_button', step: stepName, button: blockName });
});
```

<Tip>
  Um zu erfahren, ob der Klick den Besucher tatsächlich weitergebracht hat, kombinieren Sie es mit `ll-quiz-step-leave` (hat es) oder `ll-quiz-validation-error` (hat es nicht).
</Tip>

## ll-quiz-validation-error

Wird ausgelöst, wenn der Versuch, einen Schritt zu verlassen, blockiert wurde, weil etwas darin ungültig ist. Sie erhalten ein Event pro Versuch, nachdem alle Prüfungen abgeschlossen sind (einschließlich der Serverprüfungen von E-Mail-, Telefon- und OTP-Feldern), mit genau den Fehlern, die der Besucher sieht. Ausgeblendete Blöcke sind nie enthalten.

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

<ResponseField name="source" type="'user' | 'api' | 'system'">
  `user`: eine Schaltfläche oder eine navigierende Option. `api`: Ihr Skript (`validateStep()`, `goNext()`, `goToStep()`, `submit()`). `system`: das Quiz wollte von selbst weitergehen (Loader, Countdown, Zahlung)
</ResponseField>

<ResponseField name="triggerBlockId" type="string">
  Die Schaltfläche oder Option, die es ausgelöst hat; bei `api` leer
</ResponseField>

<ResponseField name="triggerBlockName" type="string">
  Bei `api` leer
</ResponseField>

<ResponseField name="errors" type="array">
  Ein Eintrag pro fehlerhaftem Block, in Schrittreihenfolge: `blockId`, `blockName`, `blockType` und `messages` (die angezeigten Texte; der erste wird dargestellt)
</ResponseField>

Es wird nicht ausgelöst, wenn der Schritt gültig ist, wenn die Previous-Schaltfläche genutzt wird (sie validiert nie) oder bei einem Auswahlklick, der nicht navigiert.

```javascript theme={null}
window.addEventListener('ll-quiz-validation-error', (event) => {
  const { stepName, errors, llQuizApi } = event.detail;

  // Herausfinden, welche Felder Besucher aufhalten
  window.dataLayer?.push({ event: 'quiz_blocked', step: stepName, fields: errors.map((e) => e.blockName) });

  // Und ihnen helfen: den Cursor auf das erste setzen
  llQuizApi.getBlock(errors[0].blockId).focus();
});
```

## ll-quiz-google-address-select

Wird ausgelöst, wenn der Besucher in einem Google-Address-Block einen Vorschlag auswählt.

<ResponseField name="blockId" type="string" />

<ResponseField name="blockName" type="string" />

<ResponseField name="stepId" type="string" />

<ResponseField name="stepName" type="string" />

<ResponseField name="address" type="object">
  `street`, `city`, `state`, `stateShort`, `postalCode`, `country`, `countryShort`
</ResponseField>

```javascript theme={null}
window.addEventListener('ll-quiz-google-address-select', (event) => {
  const { address, llQuizApi } = event.detail;
  llQuizApi.getBlock('city').setValue(address.city);
});
```

## ll-quiz-submit

Wird ausgelöst, wenn das Quiz abgesendet und der Lead gespeichert wurde. Hier senden Sie Antworten weiter oder lösen eine Conversion aus.

<ResponseField name="stepId" type="string">
  Der Schritt, aus dem der Besucher abgesendet hat
</ResponseField>

<ResponseField name="stepName" type="string" />

<ResponseField name="fields" type="Field[]">
  Alle Antworten
</ResponseField>

<ResponseField name="fieldsSimple" type="object">
  Alle Antworten als Label → Wert
</ResponseField>

<ResponseField name="response" type="any">
  Die Antwort des LanderLab-Servers oder `null`, wenn kein Lead gespeichert wurde (etwa weil das Speichern von Leads in den Quiz-Einstellungen deaktiviert ist)
</ResponseField>

```javascript theme={null}
window.addEventListener('ll-quiz-submit', (event) => {
  fetch('https://example.com/leads', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(event.detail.fieldsSimple),
  });
});
```

## ll-quiz-exit

Wird ausgelöst, wenn der Tab oder das Fenster geschlossen oder verlassen wird – basierend auf dem `pagehide`-Event des Browsers.

<Warning>
  Browser garantieren dieses Event nicht bei jedem Schließen. Nutzen Sie es für Best-Effort-Tracking mit `navigator.sendBeacon`, niemals für etwas, das zwingend passieren muss.
</Warning>

```javascript theme={null}
window.addEventListener('ll-quiz-exit', (event) => {
  const { llQuizApi } = event.detail;
  if (llQuizApi.getInfo().isSubmitted) return; // abgeschlossene Besuche sind keine Abbrüche

  const { name } = llQuizApi.getCurrentStep();
  navigator.sendBeacon('https://example.com/abandoned', JSON.stringify({ lastStep: name }));
});
```

## fields und fieldsSimple

`fields` ist eine Liste mit einem Eintrag pro beantwortetem Block:

```javascript theme={null}
[
  { id: 'firstName', label: 'First name', value: 'Ada', key: 'firstName', stepId: 'step-…', stepName: 'contact' },
  { id: 'plan', label: 'Plan', value: 'pro', key: 'plan', stepId: 'step-…', stepName: 'plan' },
]
```

`fieldsSimple` enthält dieselben Informationen als ein Objekt mit dem Label als Schlüssel – praktisch zum Weiterleiten:

```javascript theme={null}
{ 'First name': 'Ada', 'Plan': 'pro' }
```

Beide lassen ausgeblendete Blöcke und leere Antworten aus. Teilen sich zwei Blöcke ein Label, verbindet `fieldsSimple` ihre Werte mit einem Komma. Die Quiz-API liefert mit `getAnswers()` und `getAnswersSimple()` dieselben Strukturen.
