Tracking
Um Klicks, Besuche, Engagement oder andere Metriken über Ihre Nutzer:innen zu sammeln, können externe Analyse-Systeme angebunden werden. Außerdem liefern die Publikationen Custom Events, auf die gelauscht werden kann.
Für das Tracking ist es erforderlich, die Zustimmung von Nutzer:innen einzuholen. Bitte beachten Sie hierzu auch den Bereich CMP.
Integration von Analyse-Systemen
Die Integration erfolgt über den Tab Scripts in der Bearbeitungsmaske einer Publikation.
Der Tab Scripts ist ab dem Paket Starter verfügbar.
Es gibt die Möglichkeit, sowohl externe Scripte als auch Inline-Javascript zu integrieren. Das Javascript wird im <head> der Seite eingebunden. Jedes Inline-Javascript wird in einem eigenen <script>-Tag integriert, für den jeweils zusätzliche Attribute hinterlegt werden können.
Für externe Scripte stehen folgende Einstellungsmöglichkeiten zur Verfügung:
- Source: Das src-Attribut
- Load method: sync, async, defer oder preload
- Position: Auswahl, ob das Script vor oder nach den Inline-Scripts geladen werden soll
- Attributes: Möglichkeit, dem <script>-Tag weitere Attribute hinzuzufügen

Integration am Beispiel von Google Analytics 4
Google Analytics bietet die Möglichkeit, das Tracking via Google Tag Manager oder direkt über das Google-Tag einzubinden.
Google Tag Manager
Für den Google Tag Manager wird kein externes Script benötigt. Das im Google Tag Manager hinterlegte Script kann direkt inline integriert werden.

Wichtig ist, dass das dataLayer-Objekt vor der Integration des Google Tag Managers definiert wird. Der Code kann direkt im selben oder einem eigenen Code-Block integriert werden.
window.dataLayer = window.dataLayer || [];

Damit ist die Integration abgeschlossen. Alle weiteren Einstellungen werden im Google Tag Manager durchgeführt.
Google Tag
Für die direkte Einbindung des Google-Tag muss zunächst ein externes Script für die Bibliothek angelegt werden. Folgende Angaben sind erforderlich:
- Source: https://www.googletagmanager.com/gtag/js?id=[G-ID]
- Load method: async
- Position: „Before inline script"
Achten Sie darauf, dass als Position „Before inline script" ausgewählt wird, da der dataLayer nach der Einbindung des Google-Tag definiert wird.
window.dataLayer = window.dataLayer || [];
Die Integration ist damit abgeschlossen. Für die Übergabe von Events oder anderen Daten kann das dataLayer-Objekt genutzt werden.
Integration am Beispiel von Adobe Analytics
Für die Integration von Adobe Analytics ist die Einbindung des Tags-Script Voraussetzung. Diese erfolgt mithilfe eines externen Scripts innerhalb einer Publikation. Die Attribute sollten wie folgt ausgefüllt werden:
- Source: https://assets.adobedtm.com/.../launch-[ID].min.js
- Load method: async
- Position: „After inline script"
In diesem Fall muss „After inline script" ausgewählt werden. Dies ermöglicht die Übergabe von Objekten an den Adobe Data Layer.
Der Data Layer wird als Inline-Script integriert:
window.adobeDataLayer = window.adobeDataLayer || [];

Wenn Sie eine Staging-Umgebung für Ihre Publikation verwenden, können Sie das Staging-Script aus Tags hinterlegen.
Die Publikationen senden für Aktionen Custom Events, die Sie in Adobe Tags entgegennehmen und auf Custom Vars mappen können. Näheres dazu finden Sie im Kapitel Custom Events.
Die Integration ist damit abgeschlossen. Für die Übergabe von Events oder anderen Daten kann der Adobe Data Layer verwendet werden.
Integration am Beispiel der IVW
Bevor Seitenaufrufe gezählt werden können, ist es erforderlich, den INFOnline Measurement Manager zu implementieren. Hierfür stellt die IVW zwei Methoden zur Verfügung:
Mit Preload und Bundle-Loader
Integrieren Sie zunächst die bundle.js als externes Script mit der Methode preload. Erstellen Sie die Attribute as="script" und crossorigin.
Damit die Seitenaufrufe korrekt gezählt werden können, müssen Sie als Position Before inline script auswählen.

Die Methode preload generiert keinen <script>-Tag, sondern einen <link>-Tag:
<link rel="preload" href="//[domain service name]/iomm/latest/manager/base/es6/bundle.js" as="script" crossorigin>
Im nächsten Schritt wird die loader.js ebenfalls mit der Methode preload und denselben Attributen implementiert.

Zuletzt muss die loader.js synchron geladen werden.

Wenn Sie alle vorangegangenen Einstellungen korrekt implementiert haben, erzeugt dies folgende Ausgabe:
<link rel="preload" href="//[domain service name]/iomm/latest/manager/base/es6/bundle.js" as="script" crossorigin>
<link rel="preload" href="//[domain service name]/iomm/latest/manager/base/es6/loader.js" as="script" crossorigin>
<script type="text/javascript" src="https://[domain service name]/iomm/latest/bootstrap/loader.js" crossorigin></script>
Es ist empfehlenswert, exakt nach der Anleitung der IVW vorzugehen und sowohl die Reihenfolge der Tags als auch sämtliche Attribute zu beachten.
Nachdem die initialen Scripte implementiert sind, kann die Konfiguration und die eigentliche Zählung stattfinden. Hierzu verwenden Sie ein Inline-Script:
IOMm("configure", { st: "foo", dn: "data-acbd18db4c.example.com" }); // Configure IOMm
IOMm("pageview", { cp: "bar", co: "baz" }); // Count pageview

In der Dokumentation werden nur Beispielwerte angegeben. Bitte stellen Sie sicher, dass sowohl der Domain Service Name als auch die Attributswerte für die Konfiguration und das Tracking korrekt angegeben werden.
Damit ist die Integration abgeschlossen. Sollten Sie neue Zählcodes verwenden, müssen diese bei der IVW zugeordnet werden, damit die Messungen korrekt durchgeführt werden.
Ohne Preload und Bundle-Loader
Die Variante ohne Preload und Bundle-Loader unterscheidet sich vor allem in der Reihenfolge der auszuführenden Code-Blöcke.
Initial wird zunächst die stub.js synchron geladen. Hierbei ist zu beachten, dass das externe Script vor dem Inline-Javascript positioniert werden muss.

Im Nachgang erfolgt die Konfiguration Ihrer Zählung und das Pageview-Event:
IOMm("configure", { st: "foo", dn: "data-acbd18db4c.example.com" }); // Configure IOMm
IOMm("pageview", { cp: "bar", co: "baz" }); // Count pageview

Im letzten Schritt muss die bundle.js asynchron geladen werden. Hier ist zu beachten, dass das externe Script nach dem Inline-Javascript positioniert wird.

Wenn Sie alle vorangegangenen Einstellungen korrekt implementiert haben, erzeugt dies folgende Ausgabe:
<script type="text/javascript" src="https://[domain service name]/iomm/latest/bootstrap/stub.js" crossorigin></script>
<script type="text/javascript">
IOMm("configure", { st: "foo", dn: "data-acbd18db4c.example.com" }); // Configure IOMm
IOMm("pageview", { cp: "bar", co: "baz" }); // Count pageview
</script>
<script async type="text/javascript" src="https://[domain service name]/iomm/latest/manager/base/es5/bundle.js" crossorigin></script>
Custom Events
Wenn Nutzer:innen mit Ihrer Publikation interagieren, werden Custom Events ausgelöst, die von Tracking-Systemen entgegengenommen und analysiert werden können.
Custom Events werden wie folgt getriggert:
window.dispatchEvent(new CustomEvent(EventAction, {
detail: EventValue,
}));
EventValue ist ein Objekt, das wiederum Objekte, Strings oder Integer-Werte enthalten kann.
Die Events teilen sich in zwei Kategorien auf:
- Allgemeine Events — werden in jeder Publikation gefeuert, unabhängig vom Rätseltyp.
- Rätselspezifische Events — gelten nur für das jeweilige Spiel.
Allgemeine Events
Diese Events sind in allen Publikationen verfügbar:
| EventAction | Interaktion | EventValue |
|---|---|---|
| PageView | Beim Aufruf der Publikation und bei jedem weiteren Seitenaufruf darin (virtuelle Page-Impression). | JSON |
| Auth | Sobald ein(e) Nutzer:in sich über die SSO erfolgreich authentifiziert. | – |
| PaywallTriggered | Ein Inhalt hinter der Paywall wurde aufgerufen. Das Event wird bei allen Paywall-Varianten gesendet, auch wenn die Publikation die Paywall selbst anzeigt. | JSON |
| ShareResult | Spiel-Ergebnis wird über die Teilen-Funktion (z. B. WebShare-API) geteilt. | Rätselspezifischer Payload — siehe jeweilige Tabelle. |
| CopyResult | Spiel-Ergebnis wird in die Zwischenablage kopiert. | – |
| ClickOtherGame | Klick auf eine verlinkte andere Publikation (z. B. im Footer). | JSON |
| SwitchSetup | Eine Einstellung (z. B. der schwierige Modus) wurde umgeschaltet. | JSON |
| UseHeaderIcon | Ein Icon im Header (Hilfe, Statistiken, Login) wurde angeklickt. | JSON |
| UseOffCanvasMenuItem | Ein Eintrag im Off-Canvas-Menü wurde ausgewählt. | JSON |
Der Farbmodus löst kein SwitchSetup mehr aus. Er wird nicht mehr im Rätsel umgeschaltet, sondern kommt vom Gerät, aus der Adresse oder von der einbettenden Seite. Auswertungen auf setup: "dark_mode" bleiben ab der Umstellung ohne Werte. Ebenso entfällt PaywallTriggered mit feature: "dark_mode", denn das Dunkle Layout trägt keine Zugangsstufe mehr.
Worteck
Zusätzlich zu den Allgemeinen Events:
| EventAction | Interaktion | EventValue |
|---|---|---|
| GameStarted | Wird einmalig ausgelöst, wenn ein(e) Nutzer:in zum ersten Mal mit dem Rätsel interagiert. Bei einem Neustart oder der Wiederaufnahme eines bereits begonnenen Spiels wird das Event nicht erneut gefeuert. | JSON |
| GameSucceeded | Ein Wort wurde erfolgreich erraten. | JSON |
| GameFinished | Ein Spiel wurde beendet, unabhängig davon ob das Wort erraten wurde oder nicht. | JSON |
| GameFailed | Ein Spiel wurde beendet, aber das Wort nicht erraten. | JSON |
| RowCompleted | Eine Reihe wurde vervollständigt (Wort ist valide und existiert). | JSON |
| NewGame | Nach Beendigung eines Spiels wird ein neues gestartet (nur wenn mehr als ein Wort pro Tag möglich ist). | JSON |
| AllGamesCompleted | Ein(e) Nutzer:in hat alle zur Verfügung gestellten Worte zu einem Datum beendet. | JSON |
| ShareResult | Payload für das Allgemeine Event. | JSON |
Sudoku
Zusätzlich zu den Allgemeinen Events:
| EventAction | Interaktion | EventValue |
|---|---|---|
| GameStarted | Wird einmalig ausgelöst, wenn ein(e) Nutzer:in zum ersten Mal mit dem Rätsel interagiert. Bei einem Neustart oder der Wiederaufnahme eines bereits begonnenen Spiels wird das Event nicht erneut gefeuert. | JSON |
| GameFinished | Ein Sudoku wurde erfolgreich beendet. | JSON |
| GameFailed | Alle Zahlen wurden ausgefüllt, aber es sind noch Fehler enthalten. | JSON |
| RestartGame | Ein Sudoku wurde zurückgesetzt und erneut begonnen. | JSON |
| PrintGame | Ein Sudoku wurde gedruckt. | JSON |
| ShareResult | Payload für das Allgemeine Event. | JSON |
Wortwabe
Zusätzlich zu den Allgemeinen Events:
| EventAction | Interaktion | EventValue |
|---|---|---|
| GameStarted | Wird einmalig ausgelöst, wenn ein(e) Nutzer:in zum ersten Mal mit dem Rätsel interagiert. Bei einem Neustart oder der Wiederaufnahme eines bereits begonnenen Spiels wird das Event nicht erneut gefeuert. | JSON |
| GameFinished | Ein Spiel wurde erfolgreich beendet. | JSON |
| WordFound | Ein Wort wurde entdeckt. | JSON |
| ShuffleLetters | Die Buchstaben werden manuell gemischt. | JSON |
| ExpandWordList | Die Liste der gefundenen Wörter wurde aufgeklappt. | JSON |
| ShareResult | Payload für das Allgemeine Event. | JSON |
Kreuzworträtsel
Zusätzlich zu den Allgemeinen Events:
| EventAction | Interaktion | EventValue |
|---|---|---|
| GameStarted | Wird einmalig ausgelöst, wenn ein(e) Nutzer:in zum ersten Mal mit dem Rätsel interagiert. Bei einem Neustart oder der Wiederaufnahme eines bereits begonnenen Spiels wird das Event nicht erneut gefeuert. | JSON |
| GameFinished | Das Kreuzworträtsel wurde erfolgreich beendet. | JSON |
| RestartGame | Das Kreuzworträtsel wurde zurückgesetzt und erneut begonnen. | JSON |
| ShareResult | Payload für das Allgemeine Event. | JSON |
Kinonym
Zusätzlich zu den Allgemeinen Events:
| EventAction | Interaktion | EventValue |
|---|---|---|
| GameStarted | Wird einmalig ausgelöst, wenn ein(e) Nutzer:in zum ersten Mal mit dem Rätsel interagiert, also einen Begriff aufdeckt oder einen Titel rät. Bei der Wiederaufnahme eines bereits begonnenen Spiels wird das Event nicht erneut gefeuert. | JSON |
| RevealClue | Ein weiterer Begriff wurde aufgedeckt. revealed nennt die Anzahl der danach sichtbaren Begriffe. | JSON |
| GameFinished | Ein Spiel wurde beendet, unabhängig davon ob der Titel erraten wurde. won unterscheidet die beiden Fälle, earned nennt die erreichten Punkte (bei einer Niederlage 0), revealed die Anzahl der aufgedeckten Begriffe und wrong_guesses die Anzahl der Fehlversuche. | JSON |
| GameFailed | Ein Spiel wurde beendet, aber der Titel nicht erraten. Das schließt das Aufgeben ein. Der Payload entspricht GameFinished. | JSON |
Die geratenen Titel werden nicht übertragen, wrong_guesses enthält ausschließlich deren Anzahl.
Events im iFrame
Ist Ihre Publikation per Iframe oder Script eingebunden, endet ein Custom-Event an der Grenze des Iframes. Ihre Publikation reicht deshalb jedes der oben genannten Events per postMessage an die umgebende Seite weiter. Dort lassen sie sich an ein Analyse-System weiterleiten oder zur Steuerung einer Paywall nutzen.
Jede postMessage-Nachricht trägt drei Properties:
| Property | Bedeutung |
|---|---|
| source | Immer oliwol. Daran erkennt Ihre Seite die Nachrichten der Publikation. |
| event | Der Name des Events, etwa PageView oder PaywallTriggered. |
| detail | Der Payload des Events, unverändert aus den Tabellen oben. |
Auf Ihrer Seite nimmt ein EventListener die Nachrichten entgegen:
window.addEventListener('message', (event) => {
if (event.origin !== 'https://sudoku.example.com') {
return;
}
if (event.data?.source !== 'oliwol') {
return;
}
console.log(event.data.event, event.data.detail);
}, false);
Ohne die Prüfung von event.origin nimmt der Listener jede Nachricht an, die auf Ihrer Seite gesendet wird, auch die fremder Skripte. Vergleichen Sie den Wert mit der Adresse Ihrer Publikation, wie im Beispiel oben.
Die Höhe des Iframes und der Farbmodus der Publikation werden über denselben Weg übertragen und tragen dieselbe Property source. Diese Nachrichten enthalten statt event und detail eine Property height beziehungsweise colorScheme. Beide sind Zustandsmeldungen und keine Events, beschrieben unter Nachrichten an Ihre Seite.
In die umgekehrte Richtung nimmt die Publikation die Meldung PaywallClosed entgegen, sobald ein eigenes Angebot der Variante Individuell geschlossen wurde. Sie trägt dieselben Properties source und event, beschrieben unter Paywall schließen.
Virtuelle Seitenaufrufe
Da es sich bei allen Publikationen um Single Page Applications (SPA) handelt, wird beim Wechseln der URL kein Seiten-Reload ausgelöst. Einige Analyse-Systeme lauschen auf das popstate-Event und können das Navigieren innerhalb von SPAs tracken.
Alle Publikationen senden das Custom-Event PageView, sobald eine Seite aufgerufen wird. Im Payload werden die Properties to und from übergeben: to liefert die Daten zur angesteuerten Seite, from enthält die Daten zur Ausgangs-URL.
Auch der erste Aufruf der Publikation wird gemeldet. Dort ist from gleich null, denn es gibt keine Seite, von der aus er erreicht wurde. In einer Einbettung ist das der einzige Hinweis auf die Ankunft im Rätsel: Die umgebende Seite zählt ihren eigenen Aufruf, nicht den des Rahmens.
{
to: {
fullPath: "/",
hash: "",
name: "Home",
params: {},
path: "/",
query: {}
},
from: null
}
Bei jedem weiteren Seitenaufruf tragen beide Properties eine Seite:
{
to: {
fullPath: "/schwierig",
hash: "",
name: "Home",
params: {
level: "schwierig"
},
path: "/schwierig",
query: {}
},
from: {
fullPath: "/",
hash: "",
name: "Home",
params: {
level: "leicht"
},
path: "/",
query: {}
}
}
Um die Daten beim Seitenwechsel an ein Analyse-System weiterzuleiten, können Sie auf das Custom-Event PageView lauschen und den Payload übergeben. Hierfür nutzen Sie ein Inline-Script und integrieren den EventListener.
Virtuelle Seitenaufrufe mit GA4
GA4 lauscht in der Standard-Konfiguration auf das popstate-Event – daher müssen virtuelle Seitenaufrufe nicht manuell übergeben werden.

Wenn Sie diese Option deaktivieren, können Seitenaufrufe wie folgt übergeben werden:
window.addEventListener("PageView", (e) => {
gtag("event", "page_view", {
page_title: document.title,
page_location: e.detail.to.fullPath
})
});
Virtuelle Seitenaufrufe mit Adobe Analytics
Für Adobe Analytics müssen Sie keinen EventListener im oliwol Publisher Tool integrieren. Das Regelset für Custom Events integrieren Sie direkt in Adobe Tags.
Virtuelle Seitenaufrufe mit IVW
window.addEventListener("PageView", (e) => {
IOMm("pageview", { cp: "[code]" });
});
Weitere Anwendungsmöglichkeiten
Das Custom-Event PageView kann auch dazu genutzt werden, Werbemittel zu aktualisieren. Nachfolgend ein Beispiel, wie Werbemittel beim Wechseln der Seite aktualisiert werden, sofern es sich bei der Zielseite und der vorherigen Seite nicht um den Statistik-Layer handelt:
window.addEventListener("PageView", (e) => {
if (e.detail && e.detail?.to?.name !== "Stats" && e.detail?.from?.name !== "Stats") {
if (typeof OBR !== "") {
OBR.extern.refreshWidget();
}
}
});
Paywall-Kontakte
Erreichen Nutzende einen Inhalt hinter der Paywall, wird das Custom-Event PaywallTriggered gesendet. Das geschieht bei allen Paywall-Varianten, also auch dann, wenn die Publikation die Paywall selbst anzeigt. Bei der Variante Individuell ist es zugleich das Signal, das eigene Angebot einzublenden.
Der Payload beschreibt die Situation, die zur Paywall geführt hat:
| Property | Immer enthalten | Bedeutung |
|---|---|---|
| state | ja | Der Zustand, der die Paywall ausgelöst hat. |
| trigger | ja | Die Art des Auslösers: page, content, navigation, feature oder archive. |
| path | ja | Der Pfad, den Nutzende angesteuert haben. |
| type | – | Die Variante der Paywall: internal, piano oder custom. |
| paywall | – | Die Kennung der konfigurierten Paywall. |
| page | – | Der interne Name der betroffenen Seite. |
| title | – | Der Titel der betroffenen Seite. |
| feature | – | Der Schlüssel einer Funktion hinter der Paywall, etwa printing. |
| date | – | Der Tag eines archivierten Rätsels im Format JJJJ-MM-TT. |
Die Auslöserarten im Einzelnen:
| trigger | Situation |
|---|---|
| page | Eine geschützte Seite wurde aufgerufen. |
| content | Ein geschützter Abschnitt innerhalb einer Seite wurde erreicht. |
| navigation | Ein geschützter Eintrag in der Navigation wurde angeklickt. |
| feature | Eine geschützte Funktion wurde benutzt. |
| archive | Ein archiviertes Rätsel oder eine größere Archivtiefe wurde angesteuert. |
Properties, die auf die jeweilige Situation nicht zutreffen, fehlen im Payload. Prüfen Sie daher auf das Vorhandensein einer Property, nicht auf einen leeren Wert.
window.addEventListener("PaywallTriggered", (event) => {
const paywall = event.detail;
if (paywall.trigger === "feature") {
// Ein Angebot, das die Funktion hinter der Paywall benennt.
console.log(paywall.feature);
}
});
Der Payload enthält keine Angaben zur Person: weder eine Kennung noch den Anmeldestatus oder die Mitgliedschaft.









