# SPA navigation

URL: https://docs.ablyft.com/de/developers/application-integration/spa-navigation/

> Führe Experiments auf Single-Page-Applications aus, in denen sich die Seite ohne Reload ändert.



Auf einer klassischen Website lädt jeder Klick eine neue Seite, und das [Snippet](https://docs.ablyft.com/de/developers/installation/snippet/) startet erneut.
In einer **Single-Page-Application (SPA)** lädt der Browser die Seite einmal, und dein Code tauscht danach die Inhalte aus.
ABlyft würde Pages und Audiences dann nur einmal beim ersten Laden prüfen.

Diese Seite erklärt die Einstellungen und Aufrufe, mit denen ABlyft deiner Navigation folgt.

## Was du entscheiden musst

Es gibt zwei Wege, ABlyft mitzuteilen, dass "die Seite sich geändert hat". Du kannst sie kombinieren.

| Ansatz                | Funktionsweise                                                                                   | Verwende ihn, wenn                                             |
| --------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
| **Page trigger**      | ABlyft beobachtet selbst die URL oder das DOM und prüft eine Page erneut, wenn sich etwas ändert | du deinen Anwendungscode nicht anfassen möchtest               |
| **`ablyft.reInit()`** | Deine Anwendung ruft ABlyft nach jeder Navigation auf                                            | dein Router einen Hook bietet oder du volle Kontrolle möchtest |

Beide benötigen die Project-Einstellung **Use SPA features**, die als Nächstes beschrieben wird.

## Project-Einstellungen für SPAs

Öffne dein Project und gehe zu **Settings → Project Settings**. Der Abschnitt **Project Activations Settings** enthält:

| Einstellung                       | Was sie bewirkt                                                                                                                                |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Use SPA features**              | Aktiviert die Features für dynamische Websites: Page-Triggering über **URL Change** oder **DOM Change** sowie **Reset JS**.                    |
| **Run only on `ablyft.reInit()`** | Das Snippet wird geladen, startet aber nur, wenn dein Code [`ablyft.reInit()`](https://docs.ablyft.com/de/developers/reference/javascript-api/#ablyftreinit) aufruft. |
| **Default Page Trigger**          | Der Trigger, den neu erstellte Pages erhalten. Standard: **Direct**.                                                                           |

Ist **Use SPA features** aktiviert, tut ABlyft zusätzlich Folgendes:

* Bevor ein Experiment erneut angewendet wird, **macht** ABlyft zuerst seinen vorherigen Durchlauf **rückgängig**: Es führt das [Reset JS](#reset-js) aus
  und entfernt das CSS, das das Experiment und seine Variation hinzugefügt hatten.
* Bei jedem neuen Durchlauf des Projects wird das CSS, das ABlyft der Seite hinzugefügt hat, entfernt und neu hinzugefügt, sodass sich Styles nicht ansammeln.
* `ablyft.reInit()` initialisiert **alle Experiments, in denen der Visitor bereits ist**, neu, sodass Resets laufen und Goals erneut angewendet werden.

> Ohne **Use SPA features** wird Reset JS nie automatisch ausgeführt. Aktiviere die Einstellung, bevor du dich auf
> Resets verlässt.

## Option 1: ABlyft die Navigation erkennen lassen

Jede Page hat einen **Trigger**, der festlegt, *wann* ABlyft das Targeting der Page prüft. Du stellst ihn an der Page unter
**Targeting & Goals → Pages** im Abschnitt **Trigger** ein. Der Standard der meisten Projects ist **Direct**: einmal prüfen, wenn ABlyft startet.

Wähle für SPAs **URL Change (history API)**, **URL Change (polling)** oder **DOM Change**. Was jeder Trigger tut, steht in
[Pages & URL targeting](https://docs.ablyft.com/de/guides/audiences-and-delivery/pages/#trigger-when-ablyft-checks-the-page).

Beim Start prüft ABlyft jede Page einmal. Danach prüft es die Page jedes Mal erneut, wenn der Trigger auslöst.

> Trigger sind eine erweiterte Einstellung. Läuft eine Page auf einem normalen Teil deiner Website mit Reload, lass sie auf **Direct**.

### Was bei jeder Prüfung passiert

1. Wenn die Page **passt** (URL-Regeln und optionale JavaScript rules) und noch nicht aktiv ist, aktiviert ABlyft sie,
   löst ihre Pageview-Goals aus und wertet ihre Experiments aus (Environments, Audiences, Traffic).
2. Ist die Page bereits aktiv und **passt nicht mehr**, deaktiviert ABlyft sie. Was mit ihren Experiments passiert,
   hängt vom **Deactivation mode** der Page ab.

### Deactivation modes

Der **Deactivation mode** der Page (siehe [Pages & URL targeting](https://docs.ablyft.com/de/guides/audiences-and-delivery/pages/#deactivation-mode)) entscheidet,
ob Reset JS läuft und ob die Page aktiv bleibt.

Wähle **Reset** für die meisten Fälle: Das Experiment verschwindet, wenn der Visitor die Seite verlässt.

## Option 2: `ablyft.reInit()` selbst aufrufen

`ablyft.reInit()` führt ABlyft auf der aktuellen Seite erneut aus: Pages und Audiences werden erneut geprüft ("rerun condition check").
Rufe es aus deinem Router auf, nachdem die neue View gerendert wurde.

```js
// Example: call after your app finished rendering a new route
function onRouteChanged() {
  if (window.ablyft && typeof window.ablyft.reInit === 'function') {
    window.ablyft.reInit();
  }
}
```

`reInit()` existiert erst, nachdem das Snippet geladen wurde, daher die Prüfung. Goals zu pushen und andere Befehle davor
funktioniert anders, siehe [Queueing](https://docs.ablyft.com/de/developers/reference/javascript-api/#use-the-api-before-the-snippet-has-loaded).

Um mit einem sauberen Zustand zu starten, zum Beispiel nach einem Login oder Sprachwechsel, verwende `ablyft.reInit({ resetStates: true })`. Die Optionen sind in der
[JavaScript API](https://docs.ablyft.com/de/developers/reference/javascript-api/#ablyftreinit) beschrieben.

### Run only on `ablyft.reInit()`

Aktiviere **Run only on `ablyft.reInit()`**, wenn ABlyft nicht von selbst starten soll. Das ist nützlich, wenn die Anwendung
zuerst bereit sein muss (zum Beispiel wenn die erste View gerendert oder die Nutzerdaten geladen sind). Das Snippet wird weiterhin geladen
und `window.ablyft` ist verfügbar, aber Experiments starten erst mit deinem ersten `reInit()`-Aufruf.

> **Vergiss den Aufruf nicht:** Ist diese Einstellung aktiv und gibt es keinen `reInit()`-Aufruf, läuft überhaupt kein Experiment.

### Auf ABlyft-Durchläufe reagieren

ABlyft sendet bei jedem Durchlauf das Event `ablyft_initialized` auf `document`, auch bei jedem `reInit()`, und unterstützt einen
`lifecycleEnd`-Listener, der nach jedem Durchlauf aufgerufen wird. Beides ist in der
[JavaScript API](https://docs.ablyft.com/de/developers/reference/javascript-api/#events) dokumentiert.

## Reset JS

Reset JS ist Code, der das **rückgängig macht**, was dein Experiment-Code getan hat, sodass eine Variation ohne Seiten-Reload wieder entfernt werden kann.
Du kannst ihn an zwei Stellen festlegen:

* im Experiment: **Experiment Level Codes → Reset JS code**,
* in einer Variation: **Code → Reset JS code**.

ABlyft führt ihn aus, wenn ein Experiment zurückgesetzt wird: bevor das Experiment erneut angewendet wird und wenn eine Page im
Modus **Reset** oder **Force-reset** deaktiviert wird (siehe oben).

Ein Beispiel mit Variation-Code und dem passenden Reset JS code findest du unter [Ein vollständiges Beispiel](https://docs.ablyft.com/de/developers/application-integration/custom-javascript/#a-complete-example).

Das CSS, das du zu Experiments und Variations hinzugefügt hast, wird automatisch entfernt; du musst nur zurücksetzen, was dein JavaScript geändert hat.
Mehr zu den Code-Feldern: [Custom JavaScript](https://docs.ablyft.com/de/developers/application-integration/custom-javascript/#where-you-can-add-code).

## Welches Setup soll ich wählen?

| Deine Anwendung                                             | Empfehlung                                                                                                                                           |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| SPA mit `pushState`-Routing                                 | Pages mit dem Trigger **URL Change (… history API)**, Deactivation mode **Reset**                                                                    |
| URL ändert sich nicht, aber Views wechseln (Tabs, Schritte) | Trigger **DOM Change** oder ein **Callback**- / **API**-Trigger, siehe [Dynamische Inhalte](https://docs.ablyft.com/de/developers/application-integration/dynamic-content/) |
| Du kontrollierst den Router und möchtest präzises Timing    | `ablyft.reInit()` in einem Router-Hook, optional mit **Run only on `ablyft.reInit()`**                                                               |

## Fehlerbehebung

* **Experiment erscheint auf der ersten Seite, aber nicht nach der Navigation:** Die Page hat noch den Trigger **Direct**, und es wird kein
  `reInit()` aufgerufen. Ändere den Trigger oder rufe `reInit()` auf.
* **Änderungen bleiben beim Verlassen der Seite bestehen:** Es wurde kein Reset JS hinzugefügt, oder **Use SPA features** ist aus.
* **Experiment läuft doppelt oder flackert:** Sowohl ein automatischer Trigger als auch `reInit()` sind im Einsatz. Eine bereits aktive
  Page wird nicht erneut aktiviert, wähle aber nach Möglichkeit einen Ansatz.
* Aktiviere den [Debug-Modus](https://docs.ablyft.com/de/developers/debugging/preview-and-live-log/#debug-mode) und beobachte die Konsole. Jede Page-Aktivierung
  wird protokolliert. Mehr unter [Debugging](https://docs.ablyft.com/de/developers/debugging/).

## Nächste Schritte

- [Dynamische Inhalte](https://docs.ablyft.com/de/developers/application-integration/dynamic-content/): Inhalte, die nach dem Laden erscheinen.
- [Custom JavaScript](https://docs.ablyft.com/de/developers/application-integration/custom-javascript/): Experiment- und Reset-Code schreiben.
- [JavaScript API](https://docs.ablyft.com/de/developers/reference/javascript-api/): Referenz für reInit(), Events und mehr.

