> ## 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-API für erweiterte Anpassungen nutzen

> Antworten auslesen, Blöcke ändern, zwischen Schritten wechseln und Ihr Quiz per JavaScript absenden.

Mit der Quiz-API kommuniziert Ihr eigenes JavaScript mit einem Quiz, während ein Besucher es ausfüllt. Sie können auslesen, was er geantwortet hat, einen Block ändern, zu einem Schritt springen oder absenden – ganz ohne das Quiz im Builder anzufassen.

Sie können sie überall einsetzen, wo JavaScript auf der Seite läuft: im Custom Code des Quiz, in einem Skript-Block oder in einem Snippet Ihres Tag-Managers.

## Die API abrufen

Die API wird Ihnen vom Event `ll-quiz-init` als `event.detail.llQuizApi` übergeben. Bewahren Sie dieses Objekt auf und nutzen Sie es, wann immer Sie es brauchen.

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

  quiz.getBlock('firstName').setValue('Ada');
});
```

<Note>
  Ihr Skript kann vor oder nach dem Laden des Quiz ausgeführt werden. Registriert es sich spät, wird `ll-quiz-init` automatisch erneut an es gesendet – dieses Muster funktioniert also immer.
</Note>

Jedes andere Quiz-Event trägt dieselbe `llQuizApi`, sodass Sie auch auf einen Schritt oder eine Antwort reagieren und direkt handeln können. Siehe [Quiz-Events](/de/features/quizzes/api/events).

## Schritte und Blöcke über den Namen

Jede Funktion, die einen Schritt oder Block entgegennimmt, akzeptiert **dessen Namen oder ID**. Namen sind die im Builder vergebenen Bezeichnungen – sie nutzen Sie im Normalfall. IDs werden generiert und sehen aus wie `block-3f9c…`.

```javascript theme={null}
quiz.getBlock('email'); // über den Namen
quiz.getBlock('block-3f9c1a2e-…'); // über die ID, gleiches Ergebnis
quiz.getBlocksByStep('contact');
```

<Tip>
  Geben Sie jedem Block und jedem Schritt im Builder einen klaren Namen. Mehr Einrichtung braucht die API nicht.
</Tip>

Tragen zwei Blöcke oder zwei Schritte denselben Namen, wird der erste in der Quiz-Reihenfolge verwendet.

## Die Antworten auslesen

`getAnswers()` gibt alle bisher gegebenen Antworten zurück, einen Eintrag pro Block. `getAnswersSimple()` liefert dieselben Antworten als einfaches Objekt mit dem Label als Schlüssel. Ausgeblendete Blöcke und leere Antworten bleiben unberücksichtigt.

```javascript theme={null}
quiz.getAnswers();
// [{ id: 'firstName', label: 'First name', value: 'Ada', key: 'firstName', stepId: 'step-…', stepName: 'contact' }, …]

quiz.getAnswersSimple();
// { 'First name': 'Ada', 'Plan': 'pro' }
```

Das sind genau die `fields` und `fieldsSimple`, die die Events mitführen – Code, der mit dem einen umgeht, beherrscht also auch das andere.

## Wissen, wo der Besucher steht

```javascript theme={null}
quiz.getCurrentStep(); // { id: 'step-…', name: 'contact', index: 1, total: 4 }
quiz.getCurrentStepBlocks(); // die Blöcke dieses Schritts
quiz.getSteps(); // [{ id, name, index }, …] in Quiz-Reihenfolge
quiz.getInfo(); // { quizId: 'quiz-…', isSubmitted: false }
```

`index` beginnt bei 0. `isSubmitted` wird true, sobald das Quiz in diesem Besuch abgesendet wurde.

## Blöcke finden

| Aufruf                      | Gibt zurück                         |
| :-------------------------- | :---------------------------------- |
| `getBlocks()`               | Jeden Block, der einen Wert enthält |
| `getBlock(nameOrId)`        | Einen Block                         |
| `getBlocksByStep(nameOrId)` | Die Blöcke eines Schritts           |
| `getCurrentStepBlocks()`    | Die Blöcke des angezeigten Schritts |

Listen enthalten nur Blöcke, die einen Wert speichern. Überschriften, Absätze, Bilder und Ähnliches erscheinen nie. `getBlock()` findet zusätzlich Schaltflächen (Continue, Previous, Submit, Button), sodass Sie deren Text ändern oder sie deaktivieren können.

<Warning>
  `getBlock()` gibt nie `undefined` zurück. Passt nichts oder kann der Block keinen Wert speichern, erhalten Sie einen Platzhalter-Block: Jeder Aufruf darauf schreibt eine Warnung ins Log und bewirkt nichts, `getValue()` gibt `""` zurück. Ihr Code stürzt nie ab – prüfen Sie aber die Konsole, wenn etwas wirkungslos bleibt.
</Warning>

<Accordion title="Welche Blöcke speichern einen Wert?">
  Eingabefelder (Text, E-Mail, Telefon, Zahl, Textarea, Datum, Geburtsdatum, Postleitzahl, Adresse, OTP), Auswahlen (Multiple Choice, Bildauswahl, Select), Checkbox, Range Slider, Upload, Unterschrift und versteckte Felder.

  Alles übrige dient der Darstellung oder Navigation: Überschrift, Absatz, Bild, Video, Trenner, Liste, Loader, Countdown, Fortschritt, Accordion, Links, Custom Code, Tracking und die Schaltflächen. Ein Aufruf von `getValue()`, `setValue()`, `reset()` oder `validate()` auf einem davon löst einen Fehler aus. Container sind transparent: Die Blöcke darin werden wie jeder andere Block gelistet.
</Accordion>

## Einen Block auslesen und ändern

Jeder zurückgegebene Block ist dieselbe Art von Objekt – die folgenden Beispiele funktionieren also bei jedem Block, der den jeweiligen Aufruf unterstützt.

### Wert

```javascript theme={null}
const name = quiz.getBlock('firstName');

name.getValue(); // 'Ada'
name.setValue('Grace');
name.reset(); // zurück auf leer
```

Ein über die API gesetzter Wert löst `ll-quiz-value-change` mit `source: 'api'` aus, sodass Ihre Listener ihn von einer Eingabe des Besuchers unterscheiden können.

<AccordionGroup>
  <Accordion title="Wertformate je Block">
    * **Checkbox**: `'checked'` oder `'unchecked'`
    * **Multiple Choice, Bildauswahl, Select**: der Wert der Option, zum Beispiel `'pro'`
    * **Multiple Choice mit mehreren Auswahlen**: die Werte, verbunden durch das im Block konfigurierte Trennzeichen
    * **Alles übrige**: der vom Besucher eingegebene Text
  </Accordion>
</AccordionGroup>

### Label und Platzhalter

```javascript theme={null}
name.getLabel(); // 'First name'
name.setLabel('Given name');

name.getPlaceholder(); // 'Ada'
name.setPlaceholder('Type your first name');

quiz.getBlock('continue-1').setLabel('Next step'); // auch Schaltflächen
```

Labels sind reiner Text – außer bei einer Checkbox, wo HTML für Links zu den Bedingungen erlaubt ist. `setLabel()` und `getLabel()` lösen bei Blöcken ohne Label einen Fehler aus.

### Optionen

Multiple-Choice-, Bildauswahl- und Select-Blöcke geben ihre Optionen preis:

```javascript theme={null}
quiz.getBlock('plan').getOptions();
// [{ id: 'option-…', label: 'Pro', value: 'pro', selected: true }, …]
```

Ein Aufruf von `getOptions()` auf einem anderen Block löst einen Fehler aus.

### Fehler und Fokus

```javascript theme={null}
name.getErrors(); // ['This field is required.'] nach fehlgeschlagener Validierung, sonst []
name.focus(); // den Cursor dorthin setzen
```

### Schaltflächen

```javascript theme={null}
const next = quiz.getBlock('continue-1');
next.disable();
await checkSomething(); // Ihre eigene asynchrone Arbeit
next.enable();
```

`enable()` und `disable()` funktionieren bei Continue-, Submit- und Button-Blöcken und lösen bei allen anderen einen Fehler aus.

### Sichtbarkeit

```javascript theme={null}
const promo = quiz.getBlock('promoCode');

promo.visibility.hide();
promo.visibility.show();
promo.visibility.get(); // true, false oder undefined (keine Überschreibung)
promo.visibility.clear(); // Ihre Überschreibung entfernen
```

Ein ausgeblendeter Block wird nicht validiert, nicht mit dem Lead übertragen und nicht angezeigt. `undefined` bedeutet, dass Sie ihn nie geändert haben – der Block folgt dann seinen eigenen Einstellungen.

## Validieren

```javascript theme={null}
const step = await quiz.validateStep('contact'); // { success: false }
const block = await quiz.getBlock('email').validate(); // { success: false, errors: ['Invalid email address.'] }
```

Die Validierung ist asynchron, weil E-Mail-, Telefon- und OTP-Felder gegen einen Server geprüft werden. Ausgeblendete Blöcke bestehen die Prüfung immer.

<Info>
  Schlägt ein Schritt fehl, löst das Quiz außerdem `ll-quiz-validation-error` mit jedem fehlerhaften Block und dessen Meldung aus, markiert mit `source: 'api'`. Ein einziger Listener kann damit sowohl die Versuche des Besuchers als auch Ihre eigenen behandeln. Details auf der [Events-Seite](/de/features/quizzes/api/events#ll-quiz-validation-error).
</Info>

## Navigieren und absenden

```javascript theme={null}
await quiz.navigation.goNext();
quiz.navigation.goBack();
await quiz.navigation.goToStep('summary'); // Name oder ID
await quiz.navigation.submit();
quiz.navigation.goToUrl('https://example.com'); // mit `true` in neuem Tab öffnen
```

`goNext()`, `goToStep()` und `submit()` validieren zuerst den angezeigten Schritt. Ist er ungültig, bleiben sie stehen, schreiben eine Warnung ins Log und lösen `ll-quiz-validation-error` aus. `goBack()` validiert nie.

`submit()` tut genau das, was die Submit-Schaltfläche des Besuchers tut: Der Lead wird gespeichert, `ll-quiz-submit` wird mit der Serverantwort ausgelöst, der Schutz gegen Mehrfachabsenden greift und die Nach-dem-Absenden-Aktion der Submit-Schaltfläche läuft. In einem Schritt ohne Submit-Schaltfläche sendet das Quiz ab und bleibt, wo es ist. Das zurückgegebene Promise wird aufgelöst, sobald all das abgeschlossen ist.

## Rezepte

<AccordionGroup>
  <Accordion title="Aus der URL vorbefüllen">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-init', (event) => {
      const quiz = event.detail.llQuizApi;
      const params = new URLSearchParams(window.location.search);

      if (params.get('email')) quiz.getBlock('email').setValue(params.get('email'));
      if (params.get('plan')) quiz.getBlock('plan').setValue(params.get('plan'));
    });
    ```
  </Accordion>

  <Accordion title="Einen eigenen Fortschrittstext anzeigen">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-step-view', (event) => {
      const { index, total } = event.detail.llQuizApi.getCurrentStep();
      document.querySelector('#progress').textContent = `Step ${index + 1} of ${total}`;
    });
    ```
  </Accordion>

  <Accordion title="Zum ersten fehlerhaften Feld springen">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-validation-error', (event) => {
      const { errors, llQuizApi } = event.detail;
      llQuizApi.getBlock(errors[0].blockId).focus();
    });
    ```
  </Accordion>

  <Accordion title="Die Continue-Schaltfläche sperren, bis Ihre eigene Prüfung besteht">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-step-view', async (event) => {
      const quiz = event.detail.llQuizApi;
      if (quiz.getCurrentStep().name !== 'eligibility') return;

      const next = quiz.getBlock('continue-eligibility');
      next.disable();
      const ok = await fetch('/api/eligible?zip=' + quiz.getBlock('zip').getValue()).then((r) => r.ok);
      if (ok) next.enable();
      else next.setLabel('Not available in your area');
    });
    ```
  </Accordion>

  <Accordion title="Einen Block nur bei einer bestimmten Antwort anzeigen">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-value-change', (event) => {
      const { blockName, value, llQuizApi } = event.detail;
      if (blockName !== 'plan') return;

      const promo = llQuizApi.getBlock('promoCode');
      value === 'premium' ? promo.visibility.show() : promo.visibility.hide();
    });
    ```
  </Accordion>

  <Accordion title="Aus Ihrer eigenen Schaltfläche heraus absenden">
    ```javascript theme={null}
    window.addEventListener('ll-quiz-init', (event) => {
      const quiz = event.detail.llQuizApi;

      document.querySelector('#my-submit').addEventListener('click', async () => {
        await quiz.navigation.submit(); // validiert zuerst; wird nach ll-quiz-submit aufgelöst
        if (quiz.getInfo().isSubmitted) window.location.href = '/thank-you';
      });
    });
    ```
  </Accordion>

  <Accordion title="Die Antworten an Ihren eigenen Endpunkt senden">
    ```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),
      });
    });
    ```
  </Accordion>
</AccordionGroup>

## Alle Funktionen auf einen Blick

| Funktion                                                                     | Was sie tut                                   |
| :--------------------------------------------------------------------------- | :-------------------------------------------- |
| `getAnswers()` / `getAnswersSimple()`                                        | Bisherige Antworten                           |
| `getCurrentStep()` / `getCurrentStepBlocks()`                                | Der angezeigte Schritt und seine Blöcke       |
| `getSteps()` / `getInfo()`                                                   | Alle Schritte; Quiz-ID, abgesendet oder nicht |
| `getBlocks()` / `getBlock()` / `getBlocksByStep()`                           | Blöcke finden                                 |
| `validateStep(nameOrId)`                                                     | Einen Schritt validieren                      |
| `navigation.goNext()` / `goBack()` / `goToStep()` / `submit()` / `goToUrl()` | Navigieren und absenden                       |

| Auf einem Block                                                       | Was es tut                                 |
| :-------------------------------------------------------------------- | :----------------------------------------- |
| `getValue()` / `setValue()` / `reset()`                               | Die Antwort                                |
| `getLabel()` / `setLabel()` / `getPlaceholder()` / `setPlaceholder()` | Texte                                      |
| `getOptions()`                                                        | Optionen eines Auswahl- oder Select-Blocks |
| `validate()` / `getErrors()` / `focus()`                              | Validierung                                |
| `enable()` / `disable()`                                              | Schaltflächen                              |
| `visibility.show()` / `hide()` / `get()` / `clear()`                  | Ein- oder ausblenden                       |
| `blockID` / `blockType` / `variableName`                              | Identität                                  |

<Accordion title="Ältere Funktionsnamen (weiterhin unterstützt)">
  Frühere Versionen hatten je Abfragetyp eine eigene Funktion. Sie funktionieren unverändert weiter, sodass Sie bereits geschriebenen Code nicht anpassen müssen. Neuer Code sollte die vereinheitlichten Funktionen verwenden.

  | Älterer Name                                          | Stattdessen verwenden |
  | :---------------------------------------------------- | :-------------------- |
  | `getBlockByID(id)` / `getBlockByName(name)`           | `getBlock()`          |
  | `getBlocksByStepID(id)` / `getBlocksByStepName(name)` | `getBlocksByStep()`   |
  | `validateStepByID(id)` / `validateStepByName(name)`   | `validateStep()`      |
</Accordion>
