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

# Android SDK

> Integrieren Sie das Kameleoon Android SDK, um Experimente auszuführen und feature flags in nativen Android-Anwendungen zu aktivieren.

Mit dem Kameleoon Android SDK können Sie feature flags in nativen mobilen Android-Anwendungen ausführen. Das Android SDK ist sowohl mit Kotlin als auch mit Java kompatibel. Das SDK lässt sich einfach in Ihre Anwendungen integrieren, und sein Speicher- und Netzwerkverbrauch ist gering.

**Erste Schritte**: Hilfe für die ersten Schritte finden Sie im [Entwicklerleitfaden](#entwicklerleitfaden).

**Changelog**: Neueste Version des Android SDK: 4.24.0 [Changelog](https://github.com/Kameleoon/client-android/blob/master/CHANGELOG.md)

**SDK-Methoden**: Die vollständige Referenzdokumentation der Methoden des Android SDK finden Sie im Abschnitt [Referenz](#referenz).

## Entwicklerleitfaden

Folgen Sie diesem Abschnitt, um das Android SDK in Ihrer Android-App zu installieren und zu konfigurieren, und um mehr über erweiterte Funktionen zu erfahren.

### Erste Schritte

Befolgen Sie diese Schritte, um das Kameleoon Android SDK in Ihrer Anwendung zu installieren und zu konfigurieren.

#### Installation

Sie können das Android SDK installieren, indem Sie die folgende Abhängigkeit in die Datei `build.gradle` Ihrer Android-App einfügen:

```java theme={null}
dependencies {
  implementation 'com.kameleoon:kameleoon-client-android:4.20.0'
}
```

#### Zusätzliche Konfiguration

Um das Verhalten des SDK anzupassen, erstellen Sie eine `.properties`-Konfigurationsdatei. Der Name und der Speicherort der Properties-Datei sind wichtig:

* Erstellen Sie die Datei im Verzeichnis `assets/` Ihrer App.
* Benennen Sie die Datei `kameleoon-client.properties`.

Sie können auch eine [Beispielkonfiguration herunterladen](/assets/developer-docs/sdks/mobile-sdks/client-configs/kameleoon-client.properties).

Dies sind die verfügbaren Eigenschaften, die Sie festlegen können:

| Schlüssel                                                                                     | Beschreibung                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | Standardwert          |
| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `refreshIntervalMinute` / `refresh_interval_minute` (*optional*)                              | Gibt das Aktualisierungsintervall in Minuten an, in dem das SDK die Konfiguration für die aktiven Experimente und feature flags abruft. Der Wert bestimmt die maximale Zeit, die benötigt wird, um Änderungen zu verbreiten, wie z. B. die Aktivierung oder Deaktivierung von feature flags oder den Start von Experimenten. Wenn nichts angegeben ist, beträgt das Standardintervall 60 Minuten. Zusätzlich steht ein [Streaming-Modus](/developer-docs/feature-experimentation/technical-reference/technical-considerations/#streaming-premium-option) zur Verfügung, der Server-Sent Events (SSE) verwendet, um neue Konfigurationen automatisch an das SDK zu übertragen und in Echtzeit anzuwenden.                                                                                                                                                                                                                     | `60` Minuten          |
| `dataExpirationIntervalMinute` / `data_expiration_interval_minute` (*optional*)               | Bezeichnet den vordefinierten Zeitraum in Minuten, in dem das SDK die Besucher und die zugehörigen Daten speichert. Jede Dateninstanz wird einzeln bewertet, sodass Sie die Zeitspanne festlegen können, in der das SDK die Daten speichert, bevor sie automatisch gelöscht werden. Wenn kein Intervall angegeben ist, löscht das SDK die Daten nicht automatisch vom Gerät.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `Integer.MAX_VALUE`   |
| `defaultTimeoutMillisecond` / `default_timeout_millisecond` (*optional*)                      | Gibt das Zeitintervall in Millisekunden an, nach dem Netzwerkanfragen des SDK ein Timeout auslösen. Setzen Sie den Wert auf `30000` Millisekunden (30 Sekunden) oder mehr, wenn Sie keine stabile Verbindung haben. Einige Methoden verfügen über zusätzliche Parameter für methodenspezifische Timeouts. Wenn Sie diese nicht explizit angeben, wird der Standardwert verwendet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | `10000` Millisekunden |
| `trackingIntervalMillisecond` / `tracking_interval_millisecond` (*optional*)                  | Gibt das Intervall für Tracking-Anfragen in Millisekunden an. Alle Besucher, die für einen feature flag ausgewertet wurden oder deren Daten geleert (flushed) wurden, werden in diese Tracking-Anfrage einbezogen, die einmal pro Intervall ausgeführt wird. Der Mindestwert ist `1000` ms und der Höchstwert `5000` ms.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `1000` ms             |
| `environment` / `environment` (*optional*)                                                    | Für Kunden, die Experimente und feature flags in mehreren Umgebungen einsetzen, gibt diese Option an, welche feature flag-Konfiguration verwendet werden soll. Standardmäßig hat jeder feature flag die Optionen `production`, `staging` und `development`. Wenn nichts angegeben ist, lautet der Standardwert `production`. [Weitere Informationen](/user-manual/experimentation/feature-experimentation/configure-your-feature-flags/manage-environments).                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `nil`                 |
| `isUniqueIdentifier` / `is_unique_identifier` (*optional*)                                    | Gibt an, dass der angegebene `visitorCode` eine eindeutige Kennung ist.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | `false`               |
| `networkDomain` / `network_domain` (*optional*)                                               | Benutzerdefinierte Domain, die von den SDKs für ausgehende Anfragen verwendet wird, häufig zum Proxying. Muss eine gültige Domain sein (z. B. example.com oder sub.example.com). Ungültige Formate werden auf den Kameleoon-Wert zurückgesetzt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `nil`                 |
| `defaultDataFile` / `default_datafile` (*optional*)                                           | Die Funktion `default_datafile` stellt sicher, dass das Kameleoon SDK immer **READY** ist, indem sie eine Fallback-Konfiguration bereitstellt, wenn keine zwischengespeicherte Datendatei vorhanden ist. Entwickler können eine gültige Konfiguration vorab laden, indem sie sie von `https://sdk-config.kameleoon.eu/v3/<sitecode>` abrufen und als `default_datafile` während der Initialisierung übergeben. Wenn ein `dateModified`-Zeitstempel (in Millisekunden) angegeben ist und neuer als die zwischengespeicherte Version ist, verwendet das SDK die Standard-Datendatei anstelle der zwischengespeicherten Version. **Wenn `dateModified` weggelassen wird, wird die Standard-Datendatei nur angewendet, wenn keine zwischengespeicherte Version vorhanden ist**. Dadurch wird sichergestellt, dass das SDK immer über eine gültige Konfiguration verfügt, sei es Standard, zwischengespeichert oder aktualisiert. | `nil`                 |
| `activityTrackingIntervalMillisecond` / `activity_tracking_interval_millisecond` (*optional*) | Legt fest, wie oft das SDK ein Aktivitätsereignis sendet, um die Sitzung des Besuchers zu verlängern. Der Mindest- und der Standardwert betragen jeweils `60 000` ms; jeder niedrigere Wert ungleich null wird ignoriert und stattdessen der Standardwert angewendet. Setzen Sie den Wert auf `0`, um das periodische Aktivitäts-Tracking zu deaktivieren; in diesem Fall wird beim Start nur ein einziges Aktivitätsereignis gesendet. Das Ändern dieses Wertes hat Nebenwirkungen; lesen Sie daher zuerst [diesen Abschnitt](#using-activitytrackingintervalmillisecond).                                                                                                                                                                                                                                                                                                                                                  | `60 000` ms           |

<Note>
  Wenn Sie einen `visitorCode` angeben und den Parameter `isUniqueIdentifier` auf `true` setzen, verwenden die SDK-Methoden den Wert `visitorCode` als eindeutige Besucherkennung, was für [geräteübergreifende Experimente](/developer-docs/cross-device-experimentation) nützlich ist. Das SDK verknüpft die geleerten Daten mit dem Besucher, der mit der angegebenen Kennung verbunden ist.

  `isUniqueIdentifier` kann in anderen Sonderfällen nützlich sein, z. B. wenn Sie nicht auf den anonymen `visitorCode` zugreifen können, der dem Besucher ursprünglich zugewiesen wurde, aber Zugriff auf eine interne ID haben, die über Session-Merging mit dem anonymen Besucher verbunden ist.
</Note>

##### Verwendung von `activityTrackingIntervalMillisecond`

Der Parameter `activityTrackingIntervalMillisecond` trägt dazu bei, den Netzwerk- und Akkuverbrauch zu reduzieren, indem er steuert, wie oft das SDK ein Aktivitätsereignis sendet, um die Sitzung des Besuchers in der Data API zu verlängern. Der Standardwert und der zulässige Mindestwert betragen `60 000` ms (60 Sekunden); jeder niedrigere Wert ungleich null wird ignoriert und der Standardwert wird angewendet. Timer werden angehalten, während sich die App im Hintergrund befindet, sodass das Intervall effektiv nur voranschreitet, während die App im Vordergrund ist.

Prüfen Sie seine Auswirkungen auf die folgenden Funktionen:

1. **[Trigger für verstrichene Zeit](/user-manual/assets/triggers/create-a-trigger#visiting-behavior)**
   * Wenn die konfigurierte verstrichene Zeit kürzer als das Tracking-Intervall ist, wird der Trigger nicht wie erwartet ausgelöst.

2. **[Segmente für verstrichene Zeit](/user-manual/assets/segments/create-a-segment#visiting-behavior)**
   * Wenn die verstrichene Zeit kürzer als das Tracking-Intervall ist, werden Benutzer möglicherweise nicht wie beabsichtigt in das Segment aufgenommen.

3. **[Verweildauer-Ziele](/user-manual/assets/goals/create-a-goal#time-spent)**
   * Wenn die verstrichene Zeit kürzer als das Tracking-Intervall ist, wird das Ziel möglicherweise nie erreicht.

4. **[Zeit seit dem letzten Besuch in der Ergebnisseite](/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#filter-audience)**
   * Messungen der „Zeit seit dem letzten Besuch" werden ungenauer, wenn die verstrichene Zeit nahe oder unter dem Tracking-Intervall liegt.

5. **[Anzahl der Besuche](/user-manual/experiment-analytics/troubleshooting/data-discrepancies#how-visits-and-visitors-are-counted)**
   * Ein neuer Besuch wird nach 30 Minuten Inaktivität erstellt. Wenn das Tracking-Intervall länger als 30 Minuten ist, wird bei jedem Tracking-Intervall ein neuer Besuch erstellt.

<Warning>
  Das Setzen von `activityTrackingIntervalMillisecond` auf `0` deaktiviert das periodische Aktivitäts-Tracking vollständig. In dieser Konfiguration wird beim Anwendungsstart nur ein einziges Aktivitätsereignis gesendet, wodurch alle oben aufgeführten Funktionen unbrauchbar werden.
</Warning>

#### Initialisierung des Kameleoon Clients

Nachdem Sie das SDK in Ihrer Anwendung installiert und die App-Eigenschaften eingerichtet haben, müssen Sie den Kameleoon Client erstellen. Ein Client ist ein Singleton-Objekt, das als Brücke zwischen Ihrer Anwendung und der Kameleoon-Plattform fungiert. Er enthält alle Methoden und Eigenschaften, die Sie zum Ausführen eines feature flags benötigen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    import com.kameleoon.KameleoonClient;
    import com.kameleoon.KameleoonClientConfig;
    import com.kameleoon.KameleoonClientFactory;
    import com.kameleoon.KameleoonException;

    public class MyApplication extends Application
    {
        private KameleoonClient kameleoonClient;
        @Override
        public void onCreate() {
            super.onCreate();
            try {
                KameleoonClientConfig config = new KameleoonClientConfig.Builder()
                    .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
                    .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
                    .trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
                    .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
                    .environment("staging") // optional
                    .isUniqueIdentifier(false) // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
                    .networkDomain("example.com") // optional
                    .defaultDataFile("{...}") // optional
                    .activityTrackingIntervalMillisecond(20_000) // optional, 15_000 milliseconds by default
                    .build();
                String siteCode = "a8st4f59bj";
                String visitorCode = "yourVisitorCode";
                kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
                // or, if you want, the visitor code will be generated automatically
                kameleoonClient = KameleoonClientFactory.create(siteCode, config, getApplicationContext());
            } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
                // Exceptions indicate that provided siteCode is empty or visitorCode is invalid
            } catch (Exception exception) {
                // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
            }
        }
        public KameleoonClient getKameleoonClient() {
            return kameleoonClient;
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.kameleoon.KameleoonClientConfig
    import com.kameleoon.KameleoonClientFactory
    import com.kameleoon.KameleoonException

    class MyApplication : Application() {
        var kameleoonClient: KameleoonClient? = null
            private set

        override fun onCreate() {
            super.onCreate()
            try {
                val config = KameleoonClientConfig.Builder()
                    .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
                    .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
                    .trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
                    .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
                    .environment("staging") // optional
                    .networkDomain("example.com") // optional
                    .defaultDataFile("{...}") // optional
                    .activityTrackingIntervalMillisecond(20_000) // optional, 15_000 milliseconds by default
                    .build()
                val siteCode = "a8st4f59bj"
                val visitorCode = "yourVisitorCode"
                val kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext)
                // or if you want that visitor code will be generated automaticallyd
                kameleoonClient = KameleoonClientFactory.create(siteCode, config, applicationContext)
            } catch (e: KameleoonException.SiteCodeIsEmpty) {
                // Exception indicating that provided siteCode is empty
            } catch (e: KameleoonException.VisitorCodeInvalid) {
                // Exception indicating that provided visitor code is invalid
            } catch (e: Exception) {
                // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
            }
        }
    }
    ```
  </Tab>
</Tabs>

Während der Ausführung initialisiert die Methode `KameleoonClientFactory.create()` den Client, dieser ist jedoch nicht sofort einsatzbereit. Diese Verzögerung entsteht, weil der Kameleoon Client die aktuelle Konfiguration der feature flags (zusammen mit deren Traffic-Aufteilung) von einem Kameleoon-Remote-Server abrufen muss. Dieser Abruf erfordert Netzwerkzugriff, der nicht immer verfügbar ist. Solange der Kameleoon Client nicht vollständig bereit ist, sollten Sie keine anderen Methoden des Kameleoon Android SDK ausführen. Beachten Sie, dass nach dem ersten Abruf der feature flag-Konfiguration diese regelmäßig aktualisiert wird. Selbst wenn die Aktualisierung aus irgendeinem Grund fehlschlägt, funktioniert der Kameleoon Client weiterhin mit der vorherigen Konfiguration.

Sie können die Methode [`isReady()`](#isready) verwenden, um zu prüfen, ob die Initialisierung des Kameleoon Clients abgeschlossen ist.

Alternativ kann ein **Hilfe-Callback** die Logik zur Auslösung des feature flags und zur Implementierung der variation kapseln. Der beste Ansatz ([`isReady()`](#isready) oder **Callback**) hängt von den Vorlieben und dem genauen Anwendungsfall ab. Die Verwendung von [`isReady()`](#isready) wird empfohlen, wenn erwartet wird, dass das SDK bald einsatzbereit ist. Beispielsweise ist `isReady()` geeignet, wenn ein feature flag in einem Dialog ausgeführt wird, auf den Benutzer in den ersten Sekunden oder Minuten des Navigierens in der App wahrscheinlich nicht zugreifen werden. Ein Callback wird empfohlen, wenn eine hohe Wahrscheinlichkeit besteht, dass sich das SDK noch in der Initialisierung befindet. Beispielsweise sollte ein feature flag, der beim Anwendungsstart auf dem Bildschirm erscheint, einen Callback verwenden, der die Anwendung warten lässt, bis das SDK bereit ist oder ein bestimmter Timeout abgelaufen ist.

<Note>
  Es liegt in Ihrer Verantwortung als App-Entwickler, sicherzustellen, dass die Logik Ihres Anwendungscodes im Kontext von A/B-Tests mit Kameleoon korrekt ist. Eine gute Praxis ist es, immer davon auszugehen, dass der Anwendungsbenutzer aus dem feature flag ausgeschlossen werden kann, wenn der Kameleoon Client noch nicht bereit ist. Dieser Ausschluss ist einfach zu implementieren, da dies der Implementierung der Standard- oder Referenz-variation entspricht. Die Codebeispiele im nächsten Abschnitt zeigen Beispiele für diesen Ansatz.
</Note>

Sie sind nun bereit, Feature-Management und feature flags zu implementieren. Details zu zusätzlichen Methoden finden Sie im Abschnitt [Referenz](#referenz).

#### Best Practices für Initialisierung und Verwendung

* Es wird empfohlen, [`KameleoonClient`](#create) als Singleton so früh wie möglich nach dem Start der Anwendung zu initialisieren, da die Initialisierung einige Zeit in Anspruch nehmen kann. Da die Initialisierung asynchron ist, blockiert oder verzögert sie den Anwendungsstart nicht.
* Bevor Sie `KameleoonClient` verwenden, überprüfen Sie, ob er initialisiert ist, indem Sie die Methode [`runWhenReady`](#runwhenready) aufrufen. Andernfalls führen Versuche, den Client zu nutzen, bevor er bereit ist, zu Fehlern.
* ⚠️ Die meisten wichtigen Methoden können Ausnahmen auslösen, daher ist eine ordnungsgemäße Ausnahmebehandlung erforderlich. Lesen Sie die Dokumentation jeder verwendeten Methode, um deren potenzielle Ausnahmen zu verstehen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        KameleoonClient kameleoonClient = KameleoonClientFactory.create("<siteCode>", getApplicationContext());
    } catch (KameleoonException ignored) {}

    // Example: Apply a discount percentage based on an feature flag variable's value
    void applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000, result -> {
            double discount = 0.0;
            try {
                if (result.getOrThrow()) {
                    Variation variation = kameleoonClient.getVariation("discount");
                    discount = (double) variation.getVariables().get("discount_value").getValue();
                }
            } catch (Exception ignored) { }

            if (discount > 0) {
                applyDiscount(discount);
            }
        });
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        KameleoonClient kameleoonClient = KameleoonClientFactory.create("<siteCode>", applicationContext)
    } catch (ignored: KameleoonException) {}

    // Example: Apply a discount percentage based on a feature flag variable's value
    fun applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000) { result ->
            val discount = runCatching {
                if (result.getOrThrow()) {
                    val variation = kameleoonClient.getVariation("discount")
                    variation.variables["discount_value"]?.value as? Double
                } else {
                    null
                }
            }.getOrNull() ?: 0.0

            if (discount > 0) {
                applyDiscount(discount)
            }
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        val kameleoonClient = KameleoonClientFactory.create("<siteCode>", applicationContext)
    } catch (ignored: KameleoonException) {}

    // Example: Apply a discount percentage based on a feature flag variable's value
    suspend fun applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000).getOrNull() ?: return // Exit if initialization fails

        val discount = runCatching {
            val variation = kameleoonClient.getVariation("discount")
            variation.variables["discount_value"]?.value as? Double
        }.getOrNull() ?: 0.0

        if (discount > 0) {
            applyDiscount(discount)
        }
    }
    ```
  </Tab>
</Tabs>

#### Aktivieren eines feature flags

##### Abrufen einer Flag-Konfiguration

Um einen feature flag in Ihrem Code zu implementieren, müssen Sie zunächst den feature flag in Ihrem Kameleoon-Konto erstellen.

Um den Status oder die variation eines feature flags für einen bestimmten Benutzer zu ermitteln, sollten Sie die Methode [`getVariation()`](#getvariation) oder [`isFeatureActive()`](#isfeatureactive) verwenden, um die Konfiguration anhand des `featureKey` abzurufen.

Die Methode `getVariation()` verarbeitet sowohl einfache feature flags mit ON/OFF-Zuständen als auch komplexere flags mit mehreren variations. Die Methode ruft die passende variation für den Benutzer ab, indem sie die Feature-Regeln prüft, die variation zuweist und sie basierend auf `featureKey` und `visitorCode` zurückgibt.

Die Methode `isFeatureActive()` kann verwendet werden, wenn Sie die Konfiguration eines einfachen feature flags abrufen möchten, der nur einen ON- oder OFF-Zustand hat, im Gegensatz zu komplexeren feature flags mit mehreren variations oder Targeting-Optionen.

Wenn Ihr feature flag zugehörige Variablen hat (wie z. B. spezifische Verhaltensweisen, die mit jeder variation verknüpft sind), ermöglicht Ihnen `getVariation()` auch den Zugriff auf das [`Variation`](#variation)-Objekt, das Details über die zugewiesene variation und das zugehörige Experiment liefert. Diese Methode prüft, ob der Benutzer angesprochen wird, findet die dem Besucher zugewiesene variation und speichert sie im Speicher. Wenn `track=true`, sendet das SDK das Expositionsereignis bei der nächsten Tracking-Anfrage an das angegebene Experiment, was automatisch basierend auf dem [`tracking_interval_millisecond`](#zusätzliche-konfiguration) des SDK ausgelöst wird. Standardmäßig ist dieses Intervall auf 1000 Millisekunden (1 Sekunde) eingestellt.

Die Methode `getVariation()` ermöglicht es Ihnen zu steuern, ob das Tracking durchgeführt wird. Wenn `track=false`, werden vom SDK keine Expositionsereignisse gesendet. Dies ist nützlich, wenn Sie es vorziehen, keine Daten über das SDK zu tracken und stattdessen z. B. auf clientseitiges Tracking durch die Kameleoon-Engine zu setzen. Außerdem ist `track=false` hilfreich bei der Verwendung der Methode `getVariations()`, bei der Sie möglicherweise nur die variations für alle Flags benötigen, ohne Tracking-Ereignisse auszulösen. Weitere Informationen zur Funktionsweise des Trackings finden Sie in [diesem Artikel](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics).

##### Hinzufügen von Datenpunkten, um einen Benutzer anzusprechen oder Besuche in Berichten zu filtern/aufzuschlüsseln

Um einen Benutzer anzusprechen, stellen Sie sicher, dass Sie relevante Datenpunkte zu seinem Profil hinzugefügt haben, bevor Sie die feature variation abrufen oder prüfen, ob der flag aktiv ist. Verwenden Sie die Methode [`addData()`](#adddata), um diese Datenpunkte zum Benutzerprofil hinzuzufügen.

Um auf anderen Geräten gesammelte Datenpunkte abzurufen, verwenden Sie die Methode [`getRemoteVisitorData()`](#getremotevisitordata). Diese Methode ruft Daten asynchron von den Servern ab. Es ist wichtig, `getRemoteVisitorData()` *vor* dem Abrufen der variation oder dem Prüfen, ob der feature flag aktiv ist, aufzurufen, da diese Daten möglicherweise erforderlich sind, um einen Benutzer einer bestimmten variation zuzuweisen.

Weitere Informationen zu den verfügbaren Targeting-Bedingungen finden Sie im [ausführlichen Artikel zu diesem Thema](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

Darüber hinaus stehen die Datenpunkte, die Sie dem Besucherprofil hinzufügen, bei der Analyse Ihrer Experimente zur Verfügung, sodass Sie Ihre Ergebnisse nach Faktoren wie dem Gerät filtern und aufschlüsseln können. Die vollständige Liste finden Sie [hier](/de/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#zielgruppe-aufschlüsseln).

Wenn Sie zusätzliche Datenpunkte über die automatisch erfassten hinaus tracken möchten, können Sie die [Custom-Data-Funktion](#customdata) von Kameleoon verwenden. Mit Custom Data können Sie spezifische Informationen erfassen und analysieren, die für Ihre Experimente relevant sind. Vergessen Sie nicht, die Methode [`flush()`](#flush) aufzurufen, um die erfassten Daten zur Analyse an die Kameleoon-Server zu senden.

##### Tracking von Ziel-Konversionen

Wenn ein Benutzer eine gewünschte Aktion abschließt (z. B. einen Kauf tätigt), wird dies als Konversion aufgezeichnet. Um Konversionen zu tracken, verwenden Sie die Methode [`trackConversion()`](#trackconversion) und geben den erforderlichen Parameter `goalId` an.

Die Konversions-Tracking-Anfrage wird zusammen mit der nächsten geplanten Tracking-Anfrage gesendet, die das SDK in regelmäßigen Abständen sendet (definiert durch [`tracking_interval_millisecond`](#zusätzliche-konfiguration)). Wenn Sie es vorziehen, die Anfrage sofort zu senden, verwenden Sie die Methode [`flush()`](#flush) mit dem Parameter `instant=true`.

### Geräteübergreifende Experimente

Um Besucher zu unterstützen, die von mehreren Geräten aus auf eine App zugreifen, ermöglicht Kameleoon die Synchronisierung zuvor gesammelter Besucherdaten über alle Geräte des Besuchers hinweg sowie den Abgleich seiner Besuchshistorie geräteübergreifend durch geräteübergreifende Experimente. Fallstudien und detaillierte Informationen darüber, wie Kameleoon Daten geräteübergreifend verarbeitet, finden Sie im [Artikel über geräteübergreifende Experimente](/developer-docs/cross-device-experimentation).

#### Synchronisieren von Custom Data über Geräte hinweg

Obwohl die Synchronisierung benutzerdefinierter Zuordnungen verwendet wird, um Besucherdaten geräteübergreifend abzugleichen, ist sie nicht immer erforderlich. Im Folgenden sind zwei Szenarien aufgeführt, in denen eine Custom-Mapping-Synchronisierung nicht erforderlich ist:

**Gleiche Benutzer-ID auf allen Geräten**
Wenn auf allen Geräten konsistent dieselbe Benutzer-ID verwendet wird, wird die Synchronisierung automatisch ohne Custom-Mapping-Sync gehandhabt. Es reicht aus, die Methode `getRemoteVisitorData()` aufzurufen, wenn Sie die zwischen mehreren Geräten gesammelten Daten synchronisieren möchten.

**Multi-Server-Instanzen mit konsistenten IDs**
In komplexen Setups mit mehreren Servern (z. B. verteilte Serverinstanzen), bei denen dieselbe Benutzer-ID serverübergreifend verfügbar ist, ist die Synchronisierung zwischen Servern (mit `getRemoteVisitorData()`) ausreichend, ohne dass eine zusätzliche Custom-Mapping-Synchronisierung erforderlich ist.

Kunden, die zusätzliche Daten benötigen, können sich die Beschreibung der Methode [`getRemoteVisitorData()`](#getremotevisitordata) ansehen, um weitere Hinweise zu erhalten. Im folgenden Code wird angenommen, dass dieselbe eindeutige Kennung (in diesem Fall der `visitorCode`, der auch als `userId` bezeichnet werden kann) konsistent zwischen den beiden Geräten verwendet wird, um Daten korrekt abzurufen.

<Note>
  Wenn Sie gesammelte Daten in Echtzeit synchronisieren möchten, müssen Sie den Bereich **Visitor** für Ihre Custom Data wählen.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java title="Device A" theme={null}
    // In this, example Custom data with index `90` was set to "Visitor" scope in Kameleoon.
    final int VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90;

    kameleoonClient.addData(new CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"));
    kameleoonClient.flush();
    ```

    ```java title="Device B" theme={null}
    // Before working with the data, call `getRemoteVisitorData`.
    kameleoonClient.getRemoteVisitorData(result -> {
        // After calling, the SDK on Device B will have access to CustomData of Visitor scope defined on Device A.
        // So, "your data" will be available to target and track the visitor.
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin title="Device A" theme={null}
    // In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
    val VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90

    kameleoonClient.addData(CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"))
    kameleoonClient.flush()
    ```

    ```kotlin title="Device B" theme={null}
    // Before working with the data, call the `getRemoteVisitorData` method.
    kameleoonClient.getRemoteVisitorData { result ->
        // After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
        // So "your data" will be available for targeting and tracking for the visitor.
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin title="Device A" theme={null}
    // In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
    val VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90

    kameleoonClient.addData(CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"))
    kameleoonClient.flush()
    ```

    ```kotlin title="Device B" theme={null}
    // Before working with the data, call the `getRemoteVisitorData` method.
    kameleoonClient.getRemoteVisitorData()
    // After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
    // So "your data" will be available for targeting and tracking for the visitor.
    ```
  </Tab>
</Tabs>

#### Verwendung von Custom Data für das Session-Merging

[Geräteübergreifende Experimente](/developer-docs/cross-device-experimentation) ermöglichen es, die Historie eines Besuchers über alle seine Geräte hinweg zu kombinieren (Historien-Abgleich). Der Historien-Abgleich erlaubt das Zusammenführen verschiedener Besuchersitzungen zu einer. Um die Besuchshistorie abzugleichen, verwenden Sie [`CustomData`](#customdata), um eine eindeutige Kennung für den Besucher bereitzustellen. Weitere Informationen finden Sie in der [zugehörigen Dokumentation](/developer-docs/cross-device-experimentation/#activating-cross-device-history-reconciliation).

Nachdem der geräteübergreifende Abgleich aktiviert wurde, ruft das Aufrufen von [`getRemoteVisitorData()`](#getremotevisitordata) mit dem Parameter `userId` alle bekannten Daten für einen bestimmten Benutzer ab.

Sitzungen mit derselben Kennung erhalten in einem Experiment immer dieselbe variation. In der Visitor-Ansicht der Ergebnisseiten Ihres Experiments erscheinen diese Sitzungen als ein einzelner Besucher.

Die SDK-Konfiguration stellt sicher, dass verknüpfte Sitzungen immer dieselbe variation des Experiments sehen. Es gibt jedoch einige Einschränkungen bezüglich der geräteübergreifenden variation-Zuweisung. Diese Einschränkungen sind [hier](/developer-docs/cross-device-experimentation#critical-points-and-practical-insights) beschrieben.

Folgen Sie der Anleitung [Aktivieren des geräteübergreifenden Historien-Abgleichs](#geräteübergreifende-experimente), um Ihre Custom Data auf der Kameleoon-Plattform einzurichten.

Anschließend können Sie das SDK normal verwenden. Die folgenden Methoden können im Kontext des Session-Merging hilfreich sein:

* `getRemoteVisitorData()` mit `isUniqueIdentifier=true`, übergeben an [`KameleoonClientConfig`](#zusätzliche-konfiguration) - um Daten für alle verknüpften Besucher abzurufen.
* [`trackConversion()`](#trackconversion) oder [`flush()`](#flush) mit `isUniqueIdentifier=true`, übergeben an `KameleoonClientConfig` - um bestimmte Daten für einen bestimmten Besucher zu tracken, der mit einem anderen Besucher verknüpft ist.

<Tip>
  Da die Custom Data, die Sie als Kennung verwenden, auf den Bereich **Visitor** gesetzt sein muss, müssen Sie die [geräteübergreifende Synchronisierung von Custom Data](/developer-docs/cross-device-experimentation) verwenden, um die Kennung auf jedem Gerät mit der Methode [`getRemoteVisitorData()`](#getremotevisitordata) abzurufen.
</Tip>

Hier ist ein Beispiel für die Verwendung von Custom Data zum Session-Merging.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // In this example, `91` represents the Custom Data's index,
    // configured as a unique identifier in Kameleoon.
    final int MAPPING_INDEX = 91;
    final String FEATURE_KEY = "ff123";

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    KameleoonClient anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, getApplicationContext());
    anonymousKameleoonClient.runWhenReady(result -> {
        // ...
    });

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    Variation anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY);

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(new CustomData(MAPPING_INDEX, userId));
    anonymousKameleoonClient.flush(true);

    KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        (new KameleoonClientConfig.Builder())
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        getApplicationContext()
    );
    userKameleoonClient.runWhenReady(result -> {
        // ...
    });

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    Variation userVariation = userKameleoonClient.getVariation(FEATURE_KEY);
    boolean isSameVariation = userVariation.getKey().equals(anonymousVariation.getKey()); // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    kameleoonClient.trackConversion(123, 10.0f);

    // Additionally, the linked visitors will share all fetched remote visitor data.
    kameleoonClient.getRemoteVisitorData(result -> {
        // ...
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // In this example, `91` represents the Custom Data's index
    // configured as a unique identifier in Kameleoon.
    val MAPPING_INDEX = 91
    val FEATURE_KEY = "ff123"

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    val anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, applicationContext)
    anonymousKameleoonClient.runWhenReady { result ->
        // ...
    }

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    val anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY)

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(CustomData(MAPPING_INDEX, userId))
    anonymousKameleoonClient.flush(true)

    val userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        KameleoonClientConfig.Builder()
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        applicationContext
    )
    userKameleoonClient.runWhenReady { result ->
        // ...
    }

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    val userVariation = userKameleoonClient.getVariation(FEATURE_KEY)
    val isSameVariation = userVariation.getKey() == anonymousVariation.getKey() // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    userKameleoonClient.trackConversion(123, 10.0f)

    // Additionally, the linked visitors will share all fetched remote visitor data.
    userKameleoonClient.getRemoteVisitorData { result ->
        // ...
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin theme={null}
    // In this example, `91` represents the Custom Data's index
    // configured as a unique identifier in Kameleoon.
    val MAPPING_INDEX = 91
    val FEATURE_KEY = "ff123"

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    val anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, applicationContext)
    anonymousKameleoonClient.runWhenReady()

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    val anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY)

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(CustomData(MAPPING_INDEX, userId))
    anonymousKameleoonClient.flush(true)

    val userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        KameleoonClientConfig.Builder()
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        applicationContext
    )
    userKameleoonClient.runWhenReady()

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    val userVariation = userKameleoonClient.getVariation(FEATURE_KEY)
    val isSameVariation = userVariation.getKey() == anonymousVariation.getKey() // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    userKameleoonClient.trackConversion(123, 10.0f)

    // Additionally, the linked visitors will share all fetched remote visitor data.
    userKameleoonClient.getRemoteVisitorData()
    ```
  </Tab>
</Tabs>

In diesem Beispiel hat die Anwendung eine Login-Seite. Da die Benutzer-ID zum Zeitpunkt der Anmeldung unbekannt ist, wird ein anonymer Besucher verwendet, der automatisch vom SDK generiert wird. Der visitor code kann mit der Methode [`getVisitorCode()`](#getvisitorcode) abgerufen werden. Nachdem sich der Benutzer angemeldet hat, wird der anonyme Besucher mit der Benutzer-ID verknüpft und als eindeutige Kennung für den Besucher verwendet.

### Verwendung eines benutzerdefinierten Bucketing-Schlüssels

Standardmäßig verwendet Kameleoon eine eindeutige, anonyme Besucher-ID (`visitorCode`), um Benutzer feature flag variations zuzuweisen. Diese ID wird normalerweise auf dem Gerät des Benutzers generiert und gespeichert (in einem Browser-Cookie für client- und serverseitige SDKs – in persistentem Speicher für mobile SDKs). In bestimmten Szenarien müssen Sie jedoch möglicherweise sicherstellen, dass alle Benutzer derselben Organisation dieselbe Variante eines feature flags sehen.

Mit der Option **Custom Bucketing Key** können Sie dieses Standardverhalten überschreiben, indem Sie Ihre eigene benutzerdefinierte Kennung für das Bucketing angeben. Dieses Überschreiben stellt sicher, dass die Zuweisungslogik von Kameleoon Ihren angegebenen Schlüssel anstelle des standardmäßigen `visitorCode` verwendet.

#### Anwendungsfälle

Die Verwendung eines benutzerdefinierten Bucketing-Schlüssels ist entscheidend für die Konsistenz und Genauigkeit Ihrer feature flag-Zuweisungen, insbesondere in folgenden Situationen:

* **Experimente auf Konto- oder Organisationsebene:** Für B2B-Produkte oder Szenarien, in denen Sie alle Benutzer derselben Organisation derselben variation zuweisen möchten, können Sie eine Kennung wie eine `accountId` verwenden. Benutzerdefinierte Bucketing-Schlüssel sind entscheidend für A/B-Test-Funktionen, die ein gesamtes Team oder Unternehmen betreffen.

Durch die Implementierung eines benutzerdefinierten Bucketing-Schlüssels stellen Sie eine höhere Konsistenz und Genauigkeit in Ihren Experimenten sicher, was zu zuverlässigeren Ergebnissen und einer besseren Benutzererfahrung führt.

#### Technische Details

Wenn Sie einen benutzerdefinierten Bucketing-Schlüssel für einen feature flag konfigurieren, stellen Sie Kameleoon eine spezifische Kennung aus den Daten Ihrer Anwendung bereit:

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new CustomData(index, "newVisitorCode"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(CustomData(index, "newVisitorCode"))
    ```
  </Tab>
</Tabs>

* **Bereitstellung des benutzerdefinierten Schlüssels:** Sie stellen Ihre benutzerdefinierte Kennung dem Kameleoon SDK über die Methode [`addData()`](#adddata) bereit. In dieser Methode übergeben Sie Ihren gewählten benutzerdefinierten Bucketing-Schlüssel als [`CustomData`](#customdata)-Objekt. Hier bezieht sich `newVisitorCode` auf die Kennung, die Sie für Ihr Bucketing verwenden möchten (z. B. die neue `userId` oder `accountId`).

<Warning>
  Damit der benutzerdefinierte Bucketing-Schlüssel korrekt funktioniert, muss er auch für den feature flag während der Erstellung oder Bearbeitung des Flags definiert und konfiguriert werden. Ohne diese entsprechende Konfiguration wird das Bucketing des SDK Ihren benutzerdefinierten Schlüssel nicht anwenden. Detaillierte Anweisungen zur Einrichtung in Kameleoon finden Sie in diesem [Artikel](/user-manual/experimentation/feature-experimentation/create-and-manage-flags/create-a-feature-flag#Advanced_Flag_Settings).
</Warning>

* **Bucketing-Logik:** Sobald ein benutzerdefinierter Bucketing-Schlüssel über die Methode `addData()` bereitgestellt wird, verwenden alle Hash-Berechnungen zur Zuweisung von Benutzern zu variations diesen `newVisitorCode` (Ihren benutzerdefinierten Schlüssel) anstelle des standardmäßigen `visitorCode`. Die Verwendung des `newVisitorCode` bedeutet, dass die Bucketing-Entscheidung an Ihre benutzerdefinierte Kennung gebunden ist, was konsistente Zuweisungen in verschiedenen Kontexten gewährleistet, in denen diese Kennung vorhanden ist.
* **Daten-Tracking und Analytics:** Es ist wichtig zu beachten, dass, obwohl der `newVisitorCode` (Ihr benutzerdefinierter Schlüssel) für Bucketing-Entscheidungen verwendet wird, **alle nachfolgenden Daten (z. B. Tracking-Ereignisse und Konversionen) gesendet und mit dem *ursprünglichen* `visitorCode` verknüpft werden.** Diese Trennung stellt sicher, dass Ihre Analytics individuelle Benutzerreisen und Interaktionen im weiteren Kontext Ihres Experiments genau widerspiegeln, selbst wenn das Bucketing auf einer höheren Ebene (wie einem Konto) oder über mehrere Geräte/Sitzungen hinweg durchgeführt wird. Ihre ursprünglichen Besucherdaten bleiben für umfassende Berichte erhalten.

#### Technische Anforderungen

Um einen benutzerdefinierten Bucketing-Schlüssel effektiv zu verwenden:

* Der Schlüssel muss ein `String` sein.
* Er muss für die Entität, die Sie bucketen möchten, eindeutig sein (z. B. sollte bei der Verwendung einer `userId` jede Benutzer-ID eindeutig sein).
* Der Schlüssel muss dem SDK genau zu dem Zeitpunkt zur Verfügung stehen, zu dem die feature flag-Entscheidung für diesen Benutzer oder diese Anfrage ausgewertet wird.

### Targeting-Bedingungen

Die Kameleoon SDKs unterstützen eine Vielzahl vordefinierter Targeting-Bedingungen, die Sie zur Ansprache von Benutzern in Ihren Kampagnen verwenden können. Die Liste der von diesem SDK unterstützten Bedingungen finden Sie unter [Verwenden Sie die Besuchshistorie, um Benutzer anzusprechen](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

Sie können auch Ihre eigenen [externen Daten zur Ansprache von Benutzern](/developer-docs/apis/data-api-rest/tutorials/storing-and-retrieving-external-data-to-target-users) verwenden.

### Fehlerbehandlung

Alle Methoden des **Kameleoon SDK** können **nur** `KameleoonException` oder dessen dokumentierte abgeleitete Ausnahmen auslösen (aufgeführt im Abschnitt *Exceptions Thrown* jeder Methode).
Diese Ausnahmen sind **erwartetes Verhalten** des SDK. Wenn Sie bestimmte Szenarien unterschiedlich behandeln möchten, können Sie einzelne abgeleitete Ausnahmen abfangen; andernfalls behandelt das Abfangen von `KameleoonException` alle SDK-bezogenen Fehler.

Obwohl unsere **Unit- und Integrationstests** bestätigen, dass das SDK **niemals** `Exception` oder `RuntimeException` auslöst, verstehen wir, dass das **Patchen von SDK-Versionen auf Android schwierig sein kann** und unerwartete Probleme durch **Drittanbieterbibliotheken** auftreten können, die eine `RuntimeException` auslösen könnten. Um zu verhindern, dass Ihre Anwendung in solchen seltenen Fällen abstürzt, empfehlen wir, dass Sie zusätzlich **`Exception` (oder `RuntimeException`) abfangen**, als zusätzliche Absicherung. Dies ist ausschließlich eine Vorsichtsmaßnahme und **kein erwartetes Verhalten des SDK**.

Zum Beispiel:

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        // Calling a method of the SDK
    } catch (KameleoonException e) {
        // Handling expected exceptions
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        // Calling a method of the SDK
    } catch (e: KameleoonException) {
        // Handling expected exceptions
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

### Logging

Das SDK generiert Logs, um verschiedene interne Prozesse und Probleme widerzuspiegeln.

#### Log-Level

Das SDK unterstützt die Konfiguration der Begrenzung des Loggings durch ein Log-Level.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // The `NONE` log level does not allow logging.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE);

    // The `ERROR` log level only allows logging issues that may affect the SDK's main behaviour.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR);

    // The `WARNING` log level allows logging issues which may require additional attention.
    // It extends the `ERROR` log level.
    // The `WARNING` log level is a default log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING);

    // The `INFO` log level allows logging general information on the SDK's internal processes.
    // It extends the `WARNING` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO);

    // The `DEBUG` level logs additional details about the SDK’s internal processes and extends the `INFO` level
    // with more granular. diagnostic output.
    // This information is not intended for end-user interpretation but can be sent to our support team
    // to assist with internal troubleshooting.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // The `NONE` log level allows no logging.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE)

    // The `ERROR` log level allows to log only issues that may affect the SDK's main behaviour.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR)

    // The `WARNING` log level allows to log issues which may require an attention.
    // It extends the `ERROR` log level.
    // The `WARNING` log level is a default log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING)

    // The `INFO` log level allows to log general information on the SDK's internal processes.
    // It extends the `WARNING` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO)

    // The `DEBUG` log level allows to log extra information on the SDK's internal processes.
    // It extends the `INFO` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG)
    ```
  </Tab>
</Tabs>

#### Benutzerdefinierte Behandlung von Logs

Das SDK schreibt seine Logs standardmäßig in die Konsolenausgabe. Dieses Verhalten kann überschrieben werden.

<Note>
  Die Begrenzung des Loggings durch ein Log-Level erfolgt unabhängig von der Log-Behandlungslogik.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    public class CustomLogger implements com.kameleoon.logging.Logger {
        // `log` method accepts logs from the SDK
        @Override
        public void log(com.kameleoon.logging.LogLevel level, String message) {
            // Custom log handling logic here. For example:
            switch (level) {
                case ERROR:
                    android.util.Log.e("your-log-tag", message);
                    break;
                case WARNING:
                    android.util.Log.w("your-log-tag", message);
                    break;
                case INFO:
                    android.util.Log.i("your-log-tag", message);
                    break;
                case DEBUG:
                    android.util.Log.d("your-log-tag", message);
                    break;
                default:
            }
        }
    }


    // Log level filtering is applied separately from log handling logic.
    // The custom logger will only accept logs that meet or exceed the specified log level.
    // Ensure the log level is set correctly.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG); // Optional, defaults to `LogLevel.WARNING`.
    com.kameleoon.logging.KameleoonLogger.setLogger(new CustomLogger());
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    class CustomLogger : com.kameleoon.logging.Logger {

        override fun log(level: com.kameleoon.logging.LogLevel, message: String) {
            // Custom log handling logic here. For example:
            when (level) {
                com.kameleoon.logging.LogLevel.ERROR -> android.util.Log.e("your-log-tag", message)
                com.kameleoon.logging.LogLevel.WARNING -> android.util.Log.w("your-log-tag", message)
                com.kameleoon.logging.LogLevel.INFO -> android.util.Log.i("your-log-tag", message)
                com.kameleoon.logging.LogLevel.DEBUG -> android.util.Log.d("your-log-tag", message)
                else -> {
                    // Optional: handle default case if needed
                }
            }
        }
    }

    // Log level filtering is applied separately from log handling logic.
    // The custom logger will only accept logs that meet or exceed the specified log level.
    // Ensure the log level is set correctly.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG) // Optional, defaults to `LogLevel.WARNING`.
    com.kameleoon.logging.KameleoonLogger.setLogger(CustomLogger())
    ```
  </Tab>
</Tabs>

### Übergeben des visitor codes an eine WebView

In einigen Fällen müssen Sie möglicherweise den **visitor code** von der nativen Anwendung an eine WebView übergeben, die [Engine.js](/developer-docs/web-experimentation/implementation-and-deployment/standard-implementation) oder die Web-SDKs [JavaScript](/developer-docs/sdks/web-sdks/js-sdk) oder [React](/developer-docs/sdks/web-sdks/react-js-sdk) verwendet. Das folgende Beispiel zeigt die empfohlene Vorgehensweise:

<Tabs defaultTabIndex={0}>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class WebViewActivity : AppCompatActivity() {

        private var webView: WebView? = null

        private val DEFAULT_URL = "https://example.com"
        private val COOKIE_NAME = "kameleoonVisitorCode"
        private val COOKIE_DOMAIN = ".example.com"

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)

            webView = WebView(this).also { webView ->
                setContentView(webView)
                configureWebView(DEFAULT_URL, kameleoonClient)
                webView.loadUrl(DEFAULT_URL)
            }
        }

        private fun configureWebView(url: String, kameleoonClient: KameleoonClient) {
            CookieManager.getInstance().apply {
                setCookie(
                    url,
                    "$COOKIE_NAME=${kameleoonClient.visitorCode}; Domain=$COOKIE_DOMAIN; Path=/; Secure"
                )
                flush()
            }
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin (Jetpack Compose)">
    ```kotlin theme={null}
    @Composable
    fun KameleoonCookieWebView(url: String, kameleoonClient: KameleoonClient) {
        AndroidView(
            factory = { context ->
                WebView(context).apply {
                    configureWebView(url, kameleoonClient)
                    loadUrl(url)
                }
            },
        )
    }

    private fun WebView.configureWebView(url: String, kameleoonClient: KameleoonClient) {
        val COOKIE_NAME = "kameleoonVisitorCode"
        val COOKIE_DOMAIN = ".example.com"

        CookieManager.getInstance().apply {
            setCookie(
                url,
                "$COOKIE_NAME=${kameleoonClient.visitorCode}; Domain=$COOKIE_DOMAIN; Path=/; Secure"
            )
            flush()
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class WebViewActivity extends AppCompatActivity {

        private WebView webView;

        private static final String DEFAULT_URL = "https://example.com";
        private static final String COOKIE_NAME = "kameleoonVisitorCode";
        private static final String COOKIE_DOMAIN = ".example.com";

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            webView = new WebView(this);
            setContentView(webView);
            configureWebView(webView, DEFAULT_URL, kameleoonClient);
            webView.loadUrl(url);
        }

        private void configureWebView(WebView webView, String url, KameleoonClient kameleoonClient) {
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setCookie(
                    url,
                    COOKIE_NAME + "=" + kameleoonClient.getVisitorCode() + "; Domain=" + COOKIE_DOMAIN + "; Path=/; Secure"
            );
            cookieManager.flush();
        }
    }
    ```
  </Tab>
</Tabs>

## Referenz

Dies ist die vollständige Referenzdokumentation für das Kameleoon Android SDK.

### Initialisierung

Sobald Sie das [SDK installiert](#installation) haben, ist der erste Schritt die Initialisierung von Kameleoon. Alle Interaktionen Ihrer Anwendung mit dem SDK, wie z. B. das Auslösen eines Experiments, erfolgen über dieses Kameleoon-Client-Objekt.

#### create()

Rufen Sie diese Methode vor allen anderen auf, um das SDK zu initialisieren. Diese Methode befindet sich in `com.kameleoon.KameleoonClientFactory`. Ihre App führt alle Interaktionen mit dem SDK über das resultierende `KameleoonClient`-Objekt aus, das diese Methode erstellt.

Sie können das Verhalten des SDK anpassen (z. B. die Umgebung, Anmeldedaten usw.), indem Sie ein [Konfigurationsobjekt](#zusätzliche-konfiguration) bereitstellen. Andernfalls versucht das SDK stattdessen, Ihre Konfigurationsdatei zu finden und zu verwenden.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String siteCode = "a8st4f59bj";
    try {
        // pass client configuration and visitorCode as arguments
        KameleoonClientConfig config = new KameleoonClientConfig.Builder()
            .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
            .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
            .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
            .isUniqueIdentifier(false) // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
            .environment("staging") // optional
            .build();
        String visitorCode = "yourVisitorCode";
        KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
    } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
        // Exception indicates that the provided siteCode is empty or the visitorCode is invalid
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    try {
        // generate visitorCode automatically and read client configuration from a file 'kameleoon-client.properties'
        KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, getApplicationContext());
    } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
        // Exception indicates that the provided siteCode is empty or the visitorCode is invalid
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val siteCode = "a8st4f59bj"
    try {
        // pass client configuration and visitor code as arguments
        val config = KameleoonClientConfig.Builder()
            .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
            .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
            .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
            .environment("staging") // optional
            .build();
        val visitorCode = "yourVisitorCode"
        val kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext)
    } catch (e: KameleoonException.SiteCodeIsEmpty) {
        // Exception indicating that the provided siteCode is empty
    } catch (e: KameleoonException.VisitorCodeInvalid) {
        // Exception indicating that the provided visitorCode is invalid
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    try {
        // generate visitorCode automatically and read client configuration from the 'kameleoon-client.properties' file
        val kameleoonClient = KameleoonClientFactory.create(siteCode, applicationContext)
    } catch (e: KameleoonException.SiteCodeIsEmpty) {
        // Exception indicating that the provided siteCode is empty
    } catch (e: KameleoonException.VisitorCodeInvalid) {
        // Exception indicating that the provided visitorCode is invalid
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                                | Typ                     | Beschreibung                                                                                                                                                                                                                                                                              | Standard |
| ----------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| siteCode (*erforderlich*)           | `String`                | Ein [eindeutiger Schlüssel](/user-manual/faq#how-do-i-find-my-sitecode), der das mit dem SDK verwendete Kameleoon-Projekt identifiziert.                                                                                                                                                  |          |
| visitorCode (*optional*)            | `String`                | Eine optionale Besucherkennung. Verwenden Sie nach Möglichkeit Ihre interne **User-ID**; andernfalls generiert das SDK automatisch eine.                                                                                                                                                  | `nil`    |
| config (*optional*)                 | `KameleoonClientConfig` | Optionale SDK-Konfiguration. Falls angegeben, wird sie anstelle des Lesens aus einer externen [Konfigurationsdatei](#zusätzliche-konfiguration) verwendet. Falls nicht angegeben, versucht das SDK, die Datei zu lesen; wenn die Datei fehlt, greift es auf das Standardverhalten zurück. | `nil`    |
| applicationContext (*erforderlich*) | `Context`               | Der [Kontext](https://developer.android.com/reference/android/content/Context) der Anwendung.                                                                                                                                                                                             |          |

##### Rückgabewert

| Typ               | Beschreibung                                                                                                                     |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `KameleoonClient` | Eine Instanz der Klasse `KameleoonClient`, die Ihre App dann verwenden kann, um Ihre Experimente und feature flags zu verwalten. |

##### Ausgelöste Ausnahmen

| Typ                  | Beschreibung                                                                                                            |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `VisitorCodeInvalid` | Ausnahme, die anzeigt, dass der angegebene visitor code ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `SiteCodeIsEmpty`    | Ausnahme, die anzeigt, dass der angegebene Site-Code ein leerer String und somit ein ungültiger Wert ist.               |

#### isReady()

Bei mobilen SDKs kann der Kameleoon Client nicht sofort initialisiert werden, da er einen Serveraufruf durchführen muss, um die aktuelle Konfiguration für die aktiven feature flags abzurufen. Verwenden Sie diese Methode, um zu prüfen, ob das SDK bereit ist, indem Sie `isReady()` aufrufen, bevor Sie feature flags auslösen.

Alternativ können Sie einen Callback verwenden (siehe die Methode [`runWhenReady()`](#runwhenready) für Details).

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    boolean ready = kameleoonClient.isReady();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val ready = kameleoonClient.isReady
    ```
  </Tab>
</Tabs>

##### Rückgabewert

| Typ     | Beschreibung                                                                                                                                                 |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| boolean | Boolescher Wert, der den Status des SDK darstellt. `true`, wenn der Client vollständig initialisiert ist, und `false`, wenn er noch nicht einsatzbereit ist. |

#### runWhenReady()

* 🔄 *Führt eine asynchrone Anfrage aus (wenn die Konfiguration veraltet oder nicht vorhanden ist)*

Bei mobilen SDKs kann der `KameleoonClient` nicht sofort initialisiert werden, da er einen Serveraufruf durchführen muss, um die aktuelle Konfiguration für alle feature flags abzurufen. Verwenden Sie die Methode [`runWhenReady()`](#runwhenready), um die Zeit bis zur Einsatzbereitschaft des Clients zu überbrücken. Außerdem können Sie einen maximalen Timeout-Zeitraum festlegen, um zu steuern, wie lange der Client wartet, bevor er bereit ist.

Wenn `result.getOrThrow()=true`, ist der `KameleoonClient` initialisiert und bereit, und die feature flags werden mit ihren jeweiligen variations ausgelöst. Wenn das Ergebnis `false` ist oder ein Timeout auftritt, wird die Initialisierung nicht erfolgreich abgeschlossen.

Der Callback oder der auf Coroutinen basierende Code sollte eine Logik enthalten, um die Referenz-variation anzuwenden, da der Benutzer aus dem feature flag ausgeschlossen wird, wenn ein Timeout auftritt.

<Warning>
  Da die anfängliche Konfiguration möglicherweise einen Serveraufruf erfordert, ist dieser Mechanismus asynchron. Daher sollten Sie entweder:

  * Einen `completion`-Callback als Argument für die Methode bereitstellen, um sicherzustellen, dass Sie benachrichtigt werden, wenn der `KameleoonClient` vollständig initialisiert und einsatzbereit ist.
  * Coroutinen verwenden, um asynchrone Operationen zu behandeln.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.runWhenReady(1000, result -> {
        int recommendedProductsNumber = 5; // Default control number for recommended products
        try {
            if (result.getOrThrow()) {
                Variation variation = kameleoonClient.getVariation("featureKey");
                recommendedProductsNumber = (int) variation.getVariables().get("recommendedProductsNumber").getValue();
            }
        } catch (Exception ignored) {
            // The user will not be included in the experiment results and should see the control variation
        }

        applyVariation(recommendedProductsNumber);
    });
    ```

    ##### Argumente

    | Name                             | Typ                                           | Beschreibung                                         | Standard                                                                                                |
    | -------------------------------- | --------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optional*) | `int`                                         | Timeout für den Initialisierungsprozess              | [`defaultTimeoutMillisecond`](#create) oder [`default_timeout_millisecond`](#zusätzliche-konfiguration) |
    | completion (*erforderlich*)      | `ResultCompletion<Boolean, TimeoutException>` | Der Callback, der die empfangenen Daten verarbeitet. |                                                                                                         |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.runWhenReady(1000) { result ->
        val recommendedProductsNumber = runCatching {
            if (result.getOrThrow()) {
                val variation = kameleoonClient.getVariation("featureKey")
                variation.variables["recommendedProductsNumber"]?.value as Int
            } else {
                null // The user will not be included in the experiment results and should see the control variation
            }
        }.getOrDefault(5)  // Default control number for recommended products

        applyVariation(recommendedProductsNumber)
    }
    ```

    ##### Argumente

    | Name                             | Typ                                           | Beschreibung                                         | Standard                                                                                                |
    | -------------------------------- | --------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optional*) | `Int`                                         | Timeout für den Initialisierungsprozess              | [`defaultTimeoutMillisecond`](#create) oder [`default_timeout_millisecond`](#zusätzliche-konfiguration) |
    | completion (*erforderlich*)      | `ResultCompletion<Boolean, TimeoutException>` | Der Callback, der die empfangenen Daten verarbeitet. |                                                                                                         |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Ein häufiger Fehler ist die Verwendung von Suspending-Funktionen innerhalb von `mapCatching`, `runCatching` oder einem `try-catch`-Block, ohne `CancellationException` ordnungsgemäß erneut auszulösen, was die Coroutine-Abbruchlogik stören kann. Um ein korrektes Verhalten sicherzustellen, vermeiden Sie das Aufrufen von Suspend-Funktionen innerhalb dieser Blöcke.
    </Warning>

    ```kotlin theme={null}
    viewModelScope.launch {
        kameleoonClient.runWhenReady(1000).getOrNull() ?: return@launch
        val recommendedProductsNumber = runCatching {
            val variation = kameleoonClient.getVariation("featureKey")
            variation.variables["recommendedProductsNumber"]?.value as? Int
        }.getOrNull() ?: 5 // Default control number for recommended products

        applyVariation(recommendedProductsNumber)
    }
    ```

    ##### Argumente

    | Name                             | Typ   | Beschreibung                            | Standard                                                                                                |
    | -------------------------------- | ----- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optional*) | `Int` | Timeout für den Initialisierungsprozess | [`defaultTimeoutMillisecond`](#create) oder [`default_timeout_millisecond`](#zusätzliche-konfiguration) |

    ##### Rückgabewert

    | Typ            | Beschreibung                                                                                  |
    | -------------- | --------------------------------------------------------------------------------------------- |
    | `Result<Unit>` | Ein Kotlin-`Result`, das entweder das Erfolgsergebnis oder die aufgetretene Ausnahme enthält. |
  </Tab>
</Tabs>

### Feature flags und variations

#### isFeatureActive()

* 📨 *Sendet Tracking-Daten an Kameleoon (abhängig vom Parameter `track`)*

<Note>
  Diese Methode hieß zuvor `activateFeature` und wurde in der SDK-Version `4.0.0` entfernt.
</Note>

Rufen Sie diese Methode auf, um einen Feature-Toggle zu aktivieren. Diese Methode akzeptiert einen `featureKey` als erforderliches Argument, um zu prüfen, ob die angegebene Funktion für einen Besucher aktiv ist.

Wenn der Besucher noch nie mit diesem feature flag in Verbindung gebracht wurde, gibt die Methode einen zufälligen booleschen Wert zurück (`true`, wenn dem Besucher diese Funktion angezeigt werden soll, andernfalls `false`). Wenn der Besucher bereits bei diesem feature flag registriert ist, gibt diese Methode den vorherigen `featureFlag`-Wert zurück.

Stellen Sie sicher, dass Sie eine ordnungsgemäße Fehlerbehandlung wie im Beispielcode gezeigt einrichten, um potenzielle Ausnahmen abzufangen.

<Note>
  Kameleoon verwendet Tracking, um Sitzungen und Besucher zu zählen, wenn Sie bestimmte Methoden aufrufen, wie z. B. `isFeatureActive()`, `getVariation()` oder `getVariations()`.

  Verwenden Sie den Standardwert `true` für den Parameter `track`, wenn Sie Besucher einer variation aussetzen und sie zählen müssen. Setzen Sie den Parameter `track` nur dann auf `false`, wenn Sie diese Methoden aufrufen, bevor Sie Besucher aussetzen.

  Wenn Sie z. B. `getVariations()` aufrufen, um alle variations abzurufen, bevor Sie Besucher aussetzen, setzen Sie den Parameter `track` auf `false`. Diese Einstellung verhindert, dass Kameleoon eine Sitzung verfrüht zählt. Sie können das Tracking dann später auslösen, wenn Sie den Besucher explizit aussetzen.

  Kameleoon sendet Tracking-Daten standardmäßig jede Sekunde. Sie können dieses Intervall über die Konfigurationsoption für das Tracking-Intervall auf bis zu fünf Sekunden konfigurieren. Kameleoon gruppiert Tracking-Ereignisse in eine einzige Sitzung, solange das Intervall zwischen den Ereignissen weniger als 30 Minuten beträgt. Wenn zwischen den Tracking-Ereignissen mehr als 30 Minuten vergehen, zählt Kameleoon die Ereignisse als separate Sitzungen. Ein Besuch erscheint 30 Minuten nach dem letzten aufgezeichneten Ereignis der Sitzung in Ihren Berichten.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";

    boolean hasNewCheckout = false;
    try {
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey);
        // disabling tracking
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // SDK not initialized, or feature toggle not yet activated in Kameleoon - we consider the feature inactive
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    if (hasNewCheckout)
    {
        // Implement new checkout code here
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var hasNewCheckout = false

    try {
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey)
        // disabling tracking
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
        hasNewCheckout = false
    } catch (e: KameleoonException.FeatureNotFound) {
        // SDK not initialized or feature toggle not yet activated on Kameleoon's side - we consider the feature inactive
        hasNewCheckout = false
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
        hasNewCheckout = false
    }
    if (hasNewCheckout) {
        // Implement new checkout code here
    }
    ```
  </Tab>
</Tabs>

<Warning>
  Die Methode `isFeatureActive()` bewertet die ausgelieferte Variante, nicht den Master-Flag-Status. Wenn Sie Regeln ausschließen, verwendet die Methode den Standardzustand **Dann für alle anderen ausspielen**. Wenn Sie für diesen Standardzustand **Off** wählen, gibt die Methode immer `false` zurück, auch wenn der Master-feature flag **On** ist.
</Warning>

##### Argumente

| Name       | Typ     | Beschreibung                                                                                                           |
| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| featureKey | String  | Eindeutiger Schlüssel der Funktion, die Sie einem Benutzer zugänglich machen möchten. Dieses Feld ist erforderlich.    |
| track      | boolean | Ein optionaler Parameter zum Aktivieren oder Deaktivieren des Trackings der Feature-Auswertung (standardmäßig `true`). |

##### Rückgabewert

| Typ     | Beschreibung                                               |
| ------- | ---------------------------------------------------------- |
| Boolean | Wert der Funktion, der für einen Besucher registriert ist. |

##### Ausgelöste Ausnahmen

| Typ             | Beschreibung                                                                                                                                                                                                                                                                                                                        |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SDKNotReady     | Ausnahme, die anzeigt, dass das SDK seine Initialisierung noch nicht abgeschlossen hat.                                                                                                                                                                                                                                             |
| FeatureNotFound | Ausnahme, die anzeigt, dass die angeforderte Feature-ID nicht in der internen Konfiguration des SDK gefunden wurde. Diese Ausnahme bedeutet normalerweise, dass der feature flag auf der Kameleoon-Seite noch nicht aktiviert wurde (aber der Code, der die Funktion implementiert, bereits in der Anwendung bereitgestellt wurde). |

#### getVariation()

* 📨 *Sendet Tracking-Daten an Kameleoon (abhängig vom Parameter `track`)*

Ruft die [`Variation`](#variation) ab, die einem bestimmten Besucher für einen bestimmten feature flag zugewiesen wurde.

Diese Methode benötigt `visitorCode` und `featureKey` als obligatorische Argumente. Das Argument `track` ist optional und hat standardmäßig den Wert `true`.

Sie gibt die zugewiesene `Variation` für den Besucher zurück. Wenn der Besucher mit keiner feature flag-Regel verknüpft ist, gibt die Methode die Standard-`Variation` für den angegebenen feature flag zurück.

Stellen Sie sicher, dass in Ihrem Code eine ordnungsgemäße Fehlerbehandlung implementiert ist, um potenzielle Ausnahmen zu verwalten.

<Note>
  Die Standard-variation bezeichnet die variation, die einem Besucher zugewiesen wird, wenn er keiner vordefinierten Ausspielregel für einen feature flag entspricht. Mit anderen Worten, es ist die Fallback-variation, die auf alle Benutzer angewendet wird, die nicht durch bestimmte Regeln angesprochen werden. Sie wird in einer Verwaltungsoberfläche als variation im Abschnitt „Dann für alle anderen..." dargestellt.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final String featureKey = "featureKey";
    Variation variation = null;

    try {
        variation = kameleoonClient.getVariation(featureKey);
        // disabling tracking
        variation = kameleoonClient.getVariation(featureKey, false);
    } catch (KameleoonException.SDKNotReady ex) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound ex) {
        // The feature key is not in the configuration file that has been fetched by the SDK.
    } catch (KameleoonException.FeatureEnvironmentDisabled ex) {
        // The feature flag is disabled for the environment.
    }

    if (variation != null) {
        String title = (String) variation.getVariables().get("title").getValue();

        switch (variation.getKey()) {
            case "on":
                // Main variation key is selected for visitorCode
                break;
            case "alternative_variation":
                // Alternative variation key
                break;
            default:
                // Default variation key
                break;
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "featureKey"
    var variation: Variation? = null

    try {
        variation = kameleoonClient.getVariation(featureKey)
        // disabling tracking
        variation = kameleoonClient.getVariation(featureKey, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The feature key is not yet in the configuration file that has been fetched by the SDK.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    }

    val title = variation?.variables?.get("title")?.value as? String

    when (variation?.key) {
        "on" -> {
            // Main variation key is selected for visitorCode
        }
        "alternative_variation" -> {
            // Alternative variation key
        }
        else -> {
            // Default variation key
        }
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                         | Typ       | Beschreibung                                                                                    | Standard |
| ---------------------------- | --------- | ----------------------------------------------------------------------------------------------- | -------- |
| visitorCode (*erforderlich*) | `String`  | Eindeutige Kennung des Besuchers.                                                               |          |
| featureKey (*erforderlich*)  | `String`  | Schlüssel der Funktion, die Sie einem Besucher zugänglich machen möchten.                       |          |
| track (*optional*)           | `boolean` | Ein optionaler Parameter zum Aktivieren oder Deaktivieren des Trackings der Feature-Auswertung. | `true`   |

##### Rückgabewert

| Typ         | Beschreibung                                                                                                |
| ----------- | ----------------------------------------------------------------------------------------------------------- |
| `Variation` | Eine zugewiesene [`Variation`](#variation) für einen bestimmten Besucher für einen bestimmten feature flag. |

##### Ausgelöste Ausnahmen

| Typ                          | Beschreibung                                                                                                                                                                                                                                                                                                          |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VisitorCodeInvalid`         | Ausnahme, die anzeigt, dass der angegebene visitor code ungültig ist. Er ist entweder leer oder länger als 255 Zeichen.                                                                                                                                                                                               |
| `FeatureNotFound`            | Ausnahme, die anzeigt, dass der angeforderte Feature-Schlüssel nicht in der internen Konfiguration des SDK gefunden wurde. Dies bedeutet in der Regel, dass der feature flag in der Kameleoon-App nicht aktiviert ist (aber der Code, der die Funktion implementiert, bereits in der Anwendung bereitgestellt wurde). |
| `FeatureEnvironmentDisabled` | Ausnahme, die anzeigt, dass der feature flag für die aktuelle Umgebung des Besuchers deaktiviert ist (z. B. production, staging oder development).                                                                                                                                                                    |

#### getVariations()

* 📨 *Sendet Tracking-Daten an Kameleoon (abhängig vom Parameter `track`)*

Ruft eine Map von [`Variation`](#variation)-Objekten ab, die einem bestimmten Besucher über alle feature flags hinweg zugewiesen sind.

Diese Methode iteriert über alle verfügbaren feature flags und gibt die zugewiesene `Variation` für jeden flag zurück, der mit dem angegebenen Besucher verknüpft ist. Sie nimmt `onlyActive` und `track` als optionale Argumente.

* Wenn `onlyActive` auf `true` gesetzt ist, gibt die Methode `getVariations()` feature flag variations zurück, sofern der Benutzer nicht mit der `off`-variation gebucketet ist.
* Der Parameter `track` steuert, ob die Methode die variation-Zuweisungen trackt oder nicht. Standardmäßig ist er auf `true` gesetzt. Wenn er auf `false` gesetzt ist, wird das Tracking deaktiviert.

Die zurückgegebene Map enthält feature flag-Schlüssel als Schlüssel und die entsprechenden `Variation` als Werte. Wenn für einen feature flag keine variation zugewiesen ist, gibt die Methode die Standard-`Variation` für diesen flag zurück.

Eine ordnungsgemäße Fehlerbehandlung sollte implementiert werden, um potenzielle Ausnahmen zu verwalten.

<Note>
  Die Standard-variation bezeichnet die variation, die einem Besucher zugewiesen wird, wenn er keiner vordefinierten Ausspielregel für einen feature flag entspricht. Mit anderen Worten, es ist die Fallback-variation, die auf alle Benutzer angewendet wird, die nicht durch bestimmte Regeln angesprochen werden. Sie wird in einer Verwaltungsoberfläche als variation im Abschnitt „Dann für alle anderen..." dargestellt.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        Map<String, Variation> variations = kameleoonClient.getVariations();
        // only active variations
        Map<String, Variation> variations = kameleoonClient.getVariations(true);
        // disable tracking
        Map<String, Variation> variations = kameleoonClient.getVariations(false, false);
    } catch (KameleoonException.SDKNotReady ex) {
        // Exception indicating that the SDK has not completed its initialization yet.
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        val variations = kameleoonClient.getVariations()
        // only active variations
        val variations = kameleoonClient.getVariations(true)
        // disable tracking
        val variations = kameleoonClient.getVariations(false, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                    | Typ       | Beschreibung                                                                                                                           | Standard |
| ----------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| onlyActive (*optional*) | `boolean` | Ein optionaler Parameter, der angibt, ob variations für aktive (`true`) oder alle (`false`) feature flags zurückgegeben werden sollen. | `false`  |
| track (*optional*)      | `boolean` | Ein optionaler Parameter zum Aktivieren oder Deaktivieren des Trackings der Feature-Auswertung.                                        | `true`   |

##### Rückgabewert

| Typ                      | Beschreibung                                                                                                                                      |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Map<String, Variation>` | Map, die die zugewiesenen [`Variation`](#variation)-Objekte der feature flags unter Verwendung der Schlüssel der entsprechenden Features enthält. |

##### Ausgelöste Ausnahmen

| Typ           | Beschreibung                                                     |
| ------------- | ---------------------------------------------------------------- |
| `SDKNotReady` | Zeigt an, dass das SDK noch nicht vollständig initialisiert ist. |

#### setForcedVariation()

Die Methode ermöglicht es Ihnen, einem Benutzer programmatisch eine bestimmte [`Variation`](#variation) zuzuweisen und den Standard-Auswertungsprozess zu umgehen. Dies ist besonders wertvoll für kontrollierte Experimente, bei denen die übliche Auswertungslogik nicht erforderlich ist oder übersprungen werden muss. Es kann auch in Szenarien wie Debugging oder benutzerdefiniertem Testen hilfreich sein.

Wenn eine **erzwungene** variation gesetzt wird, überschreibt sie die Echtzeit-Auswertungslogik von Kameleoon. Prozesse wie Segmentierung, Targeting-Bedingungen und algorithmische Berechnungen werden übersprungen. Um Segmentierung und Targeting-Bedingungen während eines Experiments zu erhalten, setzen Sie stattdessen `forceTargeting=false`.

Eine erzwungene variation wird gleich behandelt wie eine ausgewertete variation. Sie wird in Analytics getrackt und im Benutzerkontext wie jede standardmäßig ausgewertete variation gespeichert, um Konsistenz in der Berichterstellung zu gewährleisten.

Die Methode kann unter bestimmten Bedingungen Ausnahmen auslösen (z. B. ungültige Parameter, Benutzerkontext oder interne Probleme). Eine ordnungsgemäße Ausnahmebehandlung ist unerlässlich, um sicherzustellen, dass Ihre Anwendung stabil und ausfallsicher bleibt.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final int experimentId = 9516;
    try {
        // Forcing the variation "on" for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, "on");

        // Forcing the variation "on" while preserving segmentation and targeting conditions during the experiment
        kameleoonClient.setForcedVariation(experimentId, "on", false);

        // Resetting the forced variation for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, null);
    } catch (KameleoonException e) {
        // Handling the exception
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val experimentId = 9516
    try {
        // Forcing the variation "on" for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, "on")

        // Forcing the variation "on" while preserving segmentation and targeting conditions during the experiment
        kameleoonClient.setForcedVariation(experimentId, "on", false)

        // Resetting the forced variation for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, null)
    } catch (e: KameleoonException) {
        // Handling the exception
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                          | Typ       | Beschreibung                                                                                                                                                                            | Standard |
| ----------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| experimentId (*erforderlich*) | `int`     | **Experiment-ID**, die während des Auswertungsprozesses gezielt und ausgewählt wird.                                                                                                    |          |
| variationKey (*erforderlich*) | `String`  | **Variation Key** entsprechend einer `Variation`, die als Rückgabewert für das Experiment erzwungen werden soll. Wenn der Wert `null` ist, wird die erzwungene variation zurückgesetzt. |          |
| forceTargeting (*optional*)   | `boolean` | Gibt an, ob das Targeting für das Experiment erzwungen und übersprungen werden soll (`true`) oder wie im Standard-Auswertungsprozess angewendet werden soll (`false`).                  | `true`   |

##### Ausgelöste Ausnahmen

| Typ                         | Beschreibung                                                                                                                                                                                                                                                                      |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SDKNotReady`               | Zeigt an, dass das SDK noch nicht vollständig initialisiert ist.                                                                                                                                                                                                                  |
| `FeatureExperimentNotFound` | Ausnahme, die anzeigt, dass die angeforderte Experiment-ID nicht in der internen Konfiguration des SDK gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das entsprechende Experiment der Regel auf der Kameleoon-Seite noch nicht aktiviert wurde.                |
| `FeatureVariationNotFound`  | Ausnahme, die anzeigt, dass der angeforderte variation-Schlüssel (ID) nicht in der internen Konfiguration des SDK gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das entsprechende Experiment der variation auf der Kameleoon-Seite noch nicht aktiviert wurde. |

<Info>
  In den meisten Fällen muss nur der grundlegende Fehler `KameleoonException` behandelt werden, wie im Beispiel gezeigt. Wenn jedoch verschiedene Fehlertypen eine Reaktion erfordern, behandeln Sie jeden einzeln basierend auf den spezifischen Anforderungen. Außerdem können für erhöhte Zuverlässigkeit allgemeine Sprachfehler durch Einbeziehung von `Exception` behandelt werden.
</Info>

#### evaluateAudiences()

* 📨 *Sendet Tracking-Daten an Kameleoon*

Diese Methode bewertet Besucher anhand aller verfügbaren Audiences-Explorer-Segmente und trackt diejenigen, die übereinstimmen.

`evaluateAudiences()` sollte **nach allen relevanten Besucherdaten, die gesetzt oder aktualisiert wurden**, und **unmittelbar bevor** eine feature variation abgerufen oder ein feature flag geprüft wird, aufgerufen werden. Dieser Ansatz stellt sicher, dass der Besucher anhand der aktuellsten verfügbaren Daten ausgewertet wird, was eine genaue Audience-Zuweisung basierend auf allen Kriterien ermöglicht.

Nach dem Aufruf dieser Methode können Sie eine detaillierte Analyse der Segmentleistung im Audiences Explorer durchführen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        kameleoonClient.evaluateAudiences();
    } catch (KameleoonException e) {
        // Handling the exception
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        kameleoonClient.evaluateAudiences()
    } catch (e: KameleoonException) {
        // Handling the exception
    }
    ```
  </Tab>
</Tabs>

##### Ausgelöste Ausnahmen

| Typ           | Beschreibung                                                     |
| ------------- | ---------------------------------------------------------------- |
| `SDKNotReady` | Zeigt an, dass das SDK noch nicht vollständig initialisiert ist. |

<Info>
  In den meisten Fällen muss nur der grundlegende Fehler `KameleoonException` behandelt werden, wie im Beispiel gezeigt. Wenn jedoch verschiedene Fehlertypen eine Reaktion erfordern, behandeln Sie jeden einzeln basierend auf den spezifischen Anforderungen. Außerdem können für erhöhte Zuverlässigkeit allgemeine Sprachfehler durch Einbeziehung von `Exception` behandelt werden.
</Info>

#### getDataFile()

<Tip>
  Um alle feature flags auszuwerten, verwenden Sie [`getVariations()`](#getvariations). Diese Methode ist effizienter als das Aufrufen von `DataFile` und das Iterieren durch die Flags mit [`getVariation()`](#getvariation).
</Tip>

Gibt die aktuelle SDK-Konfiguration als [`DataFile`](#datafile)-Objekt zurück.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        DataFile dataFile = kameleoonClient.getDataFile();
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        val dataFile = kameleoonClient.dataFile
        val dateModified = dataFile.dateModified
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Rückgabewert

| Typ        | Beschreibung                                                   |
| ---------- | -------------------------------------------------------------- |
| `DataFile` | Die [`DataFile`](#datafile), die die SDK-Konfiguration enthält |

##### Ausgelöste Fehler

| Typ           | Beschreibung                                                     |
| ------------- | ---------------------------------------------------------------- |
| `SDKNotReady` | Zeigt an, dass das SDK noch nicht vollständig initialisiert ist. |

### Ziele

#### trackConversion()

* 📨 *Sendet Tracking-Daten an Kameleoon*

Verwenden Sie diese Methode, um Konversionen zu tracken. Diese Methode erfordert `goalId`, um die Konversion für dieses bestimmte [Ziel](/user-manual//assets/goals/create-a-goal) zu tracken. Außerdem akzeptiert diese Methode die Argumente `revenue`, `metadata` und `negative`.

Die Methode `trackConversion()` gibt keinen Wert zurück. Diese Methode ist nicht blockierend, da der Serveraufruf asynchron erfolgt.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final int goalId = 83023;
    kameleoonClient.trackConversion(goalId); // default revenue

    kameleoonClient.trackConversion(goalId, 10); // provided revenue == 10

    kameleoonClient.trackConversion(goalId, new CustomData(1, "metadata")); // Add metadata
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val goalId = 83023
    kameleoonClient.trackConversion(goalId) // default revenue

    kameleoonClient.trackConversion(goalId, 10f) // provided revenue == 10

    kameleoonClient.trackConversion(goalId, CustomData(1, "metadata")) // Add metadata
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                    | Typ             | Beschreibung                                                                                                                          | Standard            |
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| goalId (*erforderlich*) | `int`           | ID des Ziels.                                                                                                                         |                     |
| revenue (*optional*)    | `float`         | Umsatz der Konversion.                                                                                                                | `0`                 |
| negative (*optional*)   | `boolean`       | Definiert, ob der Umsatz positiv oder negativ ist.                                                                                    | `false`             |
| metadata (*optional*)   | `CustomData...` | Metadaten der Konversion. [Müssen zuvor in der Kameleoon-App definiert werden](/de/user-manual/assets/goals/create-a-goal#metadaten). | `new CustomData[0]` |

<Note>
  Metadaten-Werte sind über [Rohdaten-Exporte](/user-manual/experiment-analytics/analyze-results/results-page/results-page-actions#Export) und [die Ergebnisseite](/user-manual/experiment-analytics/analyze-results/data-and-metrics/goal-metadata) zugänglich.

  Wenn der Parameter `metadata` angegeben wird, verwendet Kameleoon diese angegebenen Werte für die aktuelle Konversion anstelle der zuvor mit der Methode [`addData()`](#adddata) gesammelten Werte. Wenn der Parameter weggelassen wird, verwendet Kameleoon die zuletzt getrackten Werte für diese [`CustomData`](#customdata) vor der Konversion und innerhalb desselben Besuchs.

  Kameleoon berücksichtigt nur die Metadaten-Werte, die explizit als Parameter an die Methode `trackConversion()` übergeben werden.

  Im folgenden Beispiel verknüpft Kameleoon die Konversion nur mit dem benutzerdefinierten Datenwert, der explizit als Parameter angegeben wird (hier: Index 5 mit dem Wert 'Amex Credit Card').

  <Tabs defaultTabIndex={1}>
    <Tab title="Java">
      ```java theme={null}
      kameleoonClient.addData(new CustomData(5, "Credit Card"), new CustomData(9, "Express Delivery"));
      kameleoonClient.trackConversion(1000, new CustomData(5, "Amex Credit Card"));
      ```
    </Tab>

    <Tab title="Kotlin">
      ```kotlin theme={null}
      kameleoonClient.addData(CustomData(5, "Credit Card"), CustomData(9, "Express Delivery"))
      kameleoonClient.trackConversion(1000, CustomData(5, "Amex Credit Card"))
      ```
    </Tab>
  </Tabs>
</Note>

### Ereignisse

#### onUpdateConfiguration()

<Note>
  Diese Methode hieß zuvor `updateConfigurationHandler` und wurde in der SDK-Version `4.0.0` entfernt.
</Note>

Die Methode `onUpdateConfiguration()` ermöglicht es Ihnen, das Ereignis zu behandeln, wenn die Konfiguration Daten aktualisiert hat. Sie nimmt einen Eingabeparameter, **completion**. Die completion wird aufgerufen, wenn die Konfiguration über ein Echtzeit-Konfigurationsereignis aktualisiert wird.

<Note>
  Dieser Handler wird nur ausgelöst, wenn das SDK im [Streaming-Modus](/developer-docs/feature-experimentation/technical-reference/technical-considerations#streaming-premium-option) (Server-Sent Events) läuft. Er wird **nicht** für Konfigurationsaktualisierungen aufgerufen, die im Standard-Polling-Modus (`refreshIntervalMinute`) erfolgen.
</Note>

##### Argumente

| Name       | Typ                                 | Beschreibung                                                                                                         |
| ---------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| completion | `ResultCompletion<Long, Exception>` | Der Handler, der aufgerufen wird, wenn die Konfiguration über ein Echtzeit-Konfigurationsereignis aktualisiert wird. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.onUpdateConfiguration(result -> {
        if (result.isSuccess()) {
            // result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
        }
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.onUpdateConfiguration { result ->
        if (result.isSuccess) {
            // result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
        }
    }
    ```
  </Tab>
</Tabs>

### Besucherdaten

#### getVisitorCode()

Gibt den eindeutigen visitor code zurück, der im SDK verwendet wird.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String visitorCode = kameleoonClient.getVisitorCode();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val visitorCode = kameleoonClient.visitorCode
    ```
  </Tab>
</Tabs>

##### Rückgabewert

| Typ      | Beschreibung                                                                     |
| -------- | -------------------------------------------------------------------------------- |
| `String` | String, der einen eindeutigen visitor code darstellt, der im SDK verwendet wird. |

#### addData()

Die Methode `addData()` fügt [Targeting-Daten](#datentypen) zum Speicher hinzu, damit andere Methoden die Daten verwenden können, um zu entscheiden, ob der aktuelle Besucher angesprochen werden soll oder nicht.

Die Methode `addData()` gibt keinen Wert zurück und interagiert nicht selbst mit Kameleoon-Backend-Servern. Stattdessen werden alle deklarierten Daten zur späteren Übertragung mit der Methode [`flush()`](#flush) gespeichert. Dieser Ansatz reduziert die Anzahl der Serveraufrufe, da die Daten typischerweise zu einem einzigen Serveraufruf gruppiert werden, der durch `flush()` ausgelöst wird.

Die Methode [`trackConversion()`](#trackconversion) sendet ebenfalls alle zuvor zugeordneten Daten, genau wie `flush()`. Dasselbe gilt für die Methoden [`getVariation()`](#getvariation) und [`getVariations()`](#getvariations), wenn eine Experimentierregel ausgelöst wird.

<Tip>
  Jeder Besucher kann nur eine Instanz zugeordneter Daten für die meisten Datentypen haben. [`CustomData`](#customdata) ist jedoch eine Ausnahme. Besucher können eine Instanz zugeordneter `CustomData` pro Index haben.
</Tip>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Add a single data item (tracked by default)
    kameleoonClient.addData(new CustomData(1, "value"));

    // Add multiple data items (tracked by default)
    kameleoonClient.addData(new CustomData(1, "value"), new Geolocation("France"));

    // Add multiple data items stored locally for targeting only (not sent to the Kameleoon Data API)
    kameleoonClient.addData(false, new CustomData(1, "value"), new Geolocation("France"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Add a single data item (tracked by default)
    kameleoonClient.addData(CustomData(1, "value"))

    // Add multiple data items (tracked by default)
    kameleoonClient.addData(CustomData(1, "value"), Geolocation("France"))

    // Add multiple data items stored locally for targeting only (not sent to the Kameleoon Data API)
    kameleoonClient.addData(false, CustomData(1, "value"), Geolocation("France"))
    ```
  </Tab>
</Tabs>

##### Argumente

| Name                  | Typ       | Beschreibung                                                                                                                                                                                                              | Standardwert |
| --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| track (*optional*)    | `boolean` | Gibt an, ob die hinzugefügten Daten für das Tracking berechtigt sind. Bei `false` werden die Daten lokal gespeichert und nur für die Targeting-Auswertung verwendet; sie werden nicht an die Kameleoon Data API gesendet. | `true`       |
| data (*erforderlich*) | `Data...` | Sammlung von Kameleoon-Datentypen.                                                                                                                                                                                        |              |

#### flush()

* 📨 *Sendet Tracking-Daten an Kameleoon*

`flush()` nimmt die mit einem Besucher verknüpften Kameleoon-Daten und sendet eine Tracking-Anfrage zusammen mit allen Daten, die zuvor mit der Methode `addData()` hinzugefügt wurden und noch nicht gesendet wurden, wenn eine [dieser Methoden](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics) aufgerufen wird. `flush()` ist nicht blockierend, da der Serveraufruf asynchron erfolgt.

`flush()` bietet Kontrolle darüber, wann die mit einem Besucher verknüpften Daten an die Server gesendet werden. Wenn beispielsweise `addData()` ein Dutzend Mal aufgerufen wird, wäre es ineffizient, nach jedem `addData()`-Aufruf Daten an den Server zu senden. Rufen Sie `flush()` einmal am Ende auf.

Die Methode `flush()` verwendet `visitorCode` als eindeutige Besucherkennung, was für [geräteübergreifende Experimente](/developer-docs/cross-device-experimentation) nützlich ist. Wenn Sie den Konfigurationsparameter `isUniqueIdentifier` auf `true` setzen, verknüpft das SDK die geleerten Daten mit dem Besucher, der mit der angegebenen Kennung verbunden ist.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(Device.phone());
    kameleoonClient.addData(new Conversion(32, 10f, false));

    kameleoonClient.flush(); // Interval tracking (most performant tracking method)

    kameleoonClient.flush(true); // Instant tracking
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Device.phone())
    kameleoonClient.addData(Conversion(32, 10f, false))

    kameleoonClient.flush() // Interval tracking (most performant tracking method)

    kameleoonClient.flush(true) // Instant tracking
    ```
  </Tab>
</Tabs>

##### Argumente

| Name    | Typ     | Beschreibung                                                                                                                                                                                    |
| ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| instant | boolean | Boolesches Flag, das angibt, ob die Daten sofort gesendet werden sollen (`true`) oder gemäß dem geplanten Tracking-Intervall (`false`). Dieses Feld ist optional. Der Standardwert ist `false`. |

#### getRemoteData()

* 🔄 *Führt eine asynchrone Anfrage aus*

<Note>
  Diese Methode hieß zuvor `retrieveDataFromRemoteSource` und wurde in der SDK-Version `4.0.0` entfernt.
</Note>

Verwenden Sie diese Methode, um Daten von einem Kameleoon-Remote-Server basierend auf dem aktiven `siteCode` und dem `key`-Argument (oder dem aktiven `visitorCode`, wenn `key` weggelassen wird) abzurufen. Der `visitorCode` und der `siteCode` werden in `KameleoonClientFactory.create()` angegeben. Daten können schnell und bequem mit der Kameleoon Data API auf hochskalierbaren Remote-Servern gespeichert werden. Die Anwendung kann die Daten dann mit dieser Methode abrufen.

<Warning>
  Da ein Serveraufruf erforderlich ist, ist dieser Mechanismus asynchron. Daher sollten Sie entweder:

  * Einen `completion`-Callback als Argument für die Methode bereitstellen, um sicherzustellen, dass Sie benachrichtigt werden, wenn die Daten erfolgreich abgerufen wurden.
  * Coroutinen für die asynchrone Behandlung verwenden.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.getRemoteData("key", result -> {
        try {
            JSONObject jsonObject = result.getOrThrow();
            // jsonObject contains result of request
        } catch (Exception ex) {
            // request failed with an exception
        }
    });
    ```

    ##### Argumente

    | Name                        | Typ                                       | Beschreibung                                                  | Standard |
    | --------------------------- | ----------------------------------------- | ------------------------------------------------------------- | -------- |
    | key (*optional*)            | `String`                                  | Der Schlüssel, mit dem die abzurufenden Daten verknüpft sind. | `null`   |
    | completion (*erforderlich*) | `ResultCompletion<JSONObject, Exception>` | Der Callback, der die empfangenen Daten verarbeitet.          |          |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.getRemoteData("key") { result ->
        try {
            val jsonObject: JSONObject = result.getOrThrow()
            // jsonObject contains result of request
        } catch (ex: Exception) {
            // request failed with an exception
        }
    }
    ```

    ##### Argumente

    | Name                        | Typ                                       | Beschreibung                                                  | Standard |
    | --------------------------- | ----------------------------------------- | ------------------------------------------------------------- | -------- |
    | key (*optional*)            | `String`                                  | Der Schlüssel, mit dem die abzurufenden Daten verknüpft sind. | `null`   |
    | completion (*erforderlich*) | `ResultCompletion<JSONObject, Exception>` | Der Callback, der die empfangenen Daten verarbeitet.          |          |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Ein häufiger Fehler ist die Verwendung von Suspending-Funktionen innerhalb von `mapCatching`, `runCatching` oder einem `try-catch`-Block, ohne `CancellationException` ordnungsgemäß erneut auszulösen, was die Coroutine-Abbruchlogik stören kann. Um ein korrektes Verhalten sicherzustellen, vermeiden Sie das Aufrufen von Suspend-Funktionen innerhalb dieser Blöcke.
    </Warning>

    ```kotlin theme={null}
    viewModelScope.launch {
        val jsonObject = kameleoonClient.getRemoteData("key").getOrNull() ?: return@launch
    }
    ```

    ##### Argumente

    | Name             | Typ      | Beschreibung                                                  | Standard |
    | ---------------- | -------- | ------------------------------------------------------------- | -------- |
    | key (*optional*) | `String` | Der Schlüssel, mit dem die abzurufenden Daten verknüpft sind. | `null`   |

    ##### Rückgabewert

    | Typ                  | Beschreibung                                                                                                  |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<JSONObject>` | Ein Kotlin-`Result`, das entweder den abgerufenen Wert (`JSONObject`) oder die aufgetretene Ausnahme enthält. |
  </Tab>
</Tabs>

#### getRemoteVisitorData()

* 🔄 *Führt eine asynchrone Anfrage aus*

`getRemoteVisitorData()` ist eine asynchrone Methode zum Abrufen von Kameleoon-Besuchsdaten für den Besucher von der Kameleoon Data API. Die Methode fügt Daten zum Speicher hinzu, damit andere Methoden sie bei Targeting-Entscheidungen verwenden können.

Daten, die mit dieser Methode abgerufen werden, spielen eine wichtige Rolle, wenn Sie:

* von anderen Geräten gesammelte Daten verwenden möchten.
* auf die Historie eines Benutzers zugreifen möchten, z. B. auf Custom Data, die während früherer Besuche gesammelt wurden.

Lesen Sie [diesen Artikel](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation) für ein besseres Verständnis möglicher Anwendungsfälle.

<Info>
  Standardmäßig ruft `getRemoteVisitorData()` automatisch die zuletzt gespeicherten Custom Data mit `scope=Visitor` ab und hängt sie an den Besucher an, ohne dass die Methode `addData()` aufgerufen werden muss. Dies ist besonders nützlich für die [Synchronisierung von Custom Data zwischen mehreren Geräten](/developer-docs/sdks/web-sdks/nodejs-sdk#synchronizing-custom-data-across-devices).

  Es wird empfohlen, nur auf fehlgeschlagene Ergebnisse zu prüfen. Bei Bedarf kann jedoch überprüft werden, dass die Daten dem Besucher hinzugefügt wurden und für Targeting-Zwecke verfügbar sind (oder zum Debuggen, obwohl die Verwendung von [Logging](#logging) für das Debuggen besser geeignet ist). Außerdem können Daten manuell verwaltet werden, wenn der Parameter `shouldAddData=false` übergeben wird.
</Info>

<Warning>
  Da ein Serveraufruf erforderlich ist, ist dieser Mechanismus asynchron. Daher sollten Sie entweder:

  * Einen `completion`-Callback als Argument für die Methode bereitstellen, um sicherzustellen, dass Sie benachrichtigt werden, wenn die Daten erfolgreich abgerufen und dem Besucher hinzugefügt wurden.
  * Coroutinen für die asynchrone Behandlung verwenden.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Visitor data will be fetched and automatically added for `visitorCode`.
    kameleoonClient.getRemoteVisitorData(result -> {
        if (result.isSuccess()) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    });

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`.
    kameleoonClient.getRemoteVisitorData(false, result -> {
        try {
            List<Data> visitorData = result.getOrThrow();
            // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
        } catch (Exception ex) {
            // The request failed due to an exception.
        }
    });

    // If you want to fetch custom list of data types
    RemoteVisitorDataFilter filter = RemoteVisitorDataFilter.builder()
            .previousVisitAmount(25)
            .experiments(true)
            .conversion(true)
            .build();
    kameleoonClient.getRemoteVisitorData(filter, result -> {
        if (result.isSuccess()) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    });
    ```

    ##### Argumente

    | Name                        | Typ                                       | Beschreibung                                                                                                                                                                            | Standard |
    | --------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
    | filter (*optional*)         | `RemoteVisitorDataFilter`                 | Filter, der auswählt, welche Daten aus der Besuchshistorie abgerufen werden sollen. Standardmäßig ruft die Methode `CustomData` aus dem aktuellen und dem letzten vorherigen Besuch ab. | `null`   |
    | shouldAddData (*optional*)  | `boolean`                                 | Ein Boolean, der angibt, ob die Methode die abgerufenen Daten automatisch für einen Besucher hinzufügen soll.                                                                           | `true`   |
    | completion (*erforderlich*) | `ResultCompletion<List<Data>, Exception>` | Der Callback, der die empfangenen Besucherdaten verarbeitet.                                                                                                                            |          |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added to the visitor.
    kameleoonClient.getRemoteVisitorData { result ->
        if (result.isSuccess) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    }

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
    kameleoonClient.getRemoteVisitorData(false) { result ->
        try {
            val visitorData = result.getOrThrow()
            // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
        } catch (e: Exception) {
            // The request failed due to an exception.
        }
    }

    val filter = RemoteVisitorDataFilter.builder()
        .previousVisitAmount(25)
        .experiments(true)
        .conversion(true)
        .build()
    kameleoonClient.getRemoteVisitorData(filter) { result ->
        if (result.isSuccess) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    }
    ```

    ##### Argumente

    | Name                        | Typ                                       | Beschreibung                                                                                                                                                                            | Standard |
    | --------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
    | filter (*optional*)         | `RemoteVisitorDataFilter`                 | Filter, der auswählt, welche Daten aus der Besuchshistorie abgerufen werden sollen. Standardmäßig ruft die Methode `CustomData` aus dem aktuellen und dem letzten vorherigen Besuch ab. | `null`   |
    | shouldAddData (*optional*)  | `Boolean`                                 | Ein Boolean, der angibt, ob die Methode die abgerufenen Daten automatisch für einen Besucher hinzufügen soll.                                                                           | `true`   |
    | completion (*erforderlich*) | `ResultCompletion<List<Data>, Exception>` | Der Callback, der die empfangenen Besucherdaten verarbeitet.                                                                                                                            |          |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Ein häufiger Fehler ist die Verwendung von Suspending-Funktionen innerhalb von `mapCatching`, `runCatching` oder einem `try-catch`-Block, ohne `CancellationException` ordnungsgemäß erneut auszulösen, was die Coroutine-Abbruchlogik stören kann. Um ein korrektes Verhalten sicherzustellen, vermeiden Sie das Aufrufen von Suspend-Funktionen innerhalb dieser Blöcke.
    </Warning>

    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for `visitorCode`
    viewModelScope.launch {
        kameleoonClient.getRemoteVisitorData() ?: return@launch
    }

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
    viewModelScope.launch {
        kameleoonClient.getRemoteVisitorData(shouldAddData = false)
            .onSuccess { visitorData ->
                // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
            }.onFailure { ex ->
                // request failed with exception
            }
    }

    viewModelScope.launch {
        val filter = RemoteVisitorDataFilter.builder()
            .previousVisitAmount(25)
            .experiments(true)
            .conversion(true)
            .build()
        // In general, we recommend checking only if the request fails.
        kameleoonClient.getRemoteVisitorData(filter) ?: return@launch
    }
    ```

    ##### Argumente

    | Name                       | Typ                       | Beschreibung                                                                                                                                                                            | Standard |
    | -------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
    | filter (*optional*)        | `RemoteVisitorDataFilter` | Filter, der auswählt, welche Daten aus der Besuchshistorie abgerufen werden sollen. Standardmäßig ruft die Methode `CustomData` aus dem aktuellen und dem letzten vorherigen Besuch ab. | `null`   |
    | shouldAddData (*optional*) | `Boolean`                 | Ein Boolean, der angibt, ob die Methode die abgerufenen Daten automatisch für einen Besucher hinzufügen soll.                                                                           | `true`   |

    ##### Rückgabewert

    | Typ                  | Beschreibung                                                                                                  |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<List<Data>>` | Ein Kotlin-`Result`, das entweder den abgerufenen Wert (`List<Data>`) oder die aufgetretene Ausnahme enthält. |
  </Tab>
</Tabs>

##### Verwendung der Parameter von `RemoteVisitorDataFilter`

Die Methode `getRemoteVisitorData()` bietet Flexibilität, indem sie Ihnen erlaubt, verschiedene Parameter beim Abrufen von Daten zu Besuchern zu definieren. Egal, ob Sie auf Basis von Zielen, Experimenten oder variations targeten, der gleiche Ansatz gilt für alle Datentypen.

Angenommen, Sie möchten Daten über Besucher abrufen, die ein Ziel „Bestelltransaktion" abgeschlossen haben. Sie können Parameter innerhalb der Methode `getRemoteVisitorData()` angeben, um Ihr Targeting zu verfeinern. Wenn Sie z. B. nur Benutzer ansprechen möchten, die das Ziel in ihren letzten fünf Besuchen konvertiert haben, können Sie den Parameter `previousVisitAmount` auf `5` und `conversions` auf `true` setzen.

Die in diesem Beispiel gezeigte Flexibilität ist nicht auf Zieldaten beschränkt. Sie können Parameter innerhalb der Methode `getRemoteVisitorData()` verwenden, um Daten zu einer Vielzahl von Besucherverhalten abzurufen.

<Note>
  Hier ist die Liste der verfügbaren `RemoteVisitorDataFilter`-Optionen:

  | Name                             | Typ       | Beschreibung                                                                                                                                                                                                                                                                                                                                                    | Standard |
  | -------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
  | previousVisitAmount (*optional*) | `int`     | Anzahl der vorherigen Besuche, aus denen Daten abgerufen werden sollen. Zahl zwischen `1` und `25`                                                                                                                                                                                                                                                              | `1`      |
  | currentVisit (*optional*)        | `boolean` | Bei true werden Daten des aktuellen Besuchs abgerufen.                                                                                                                                                                                                                                                                                                          | `true`   |
  | customData (*optional*)          | `boolean` | Bei true werden Custom Data abgerufen.                                                                                                                                                                                                                                                                                                                          | `true`   |
  | geolocation (*optional*)         | `boolean` | Bei true werden Geolocation-Daten abgerufen.                                                                                                                                                                                                                                                                                                                    | `false`  |
  | conversions (*optional*)         | `boolean` | Bei true werden Konversionsdaten abgerufen.                                                                                                                                                                                                                                                                                                                     | `false`  |
  | experiments (*optional*)         | `boolean` | Bei true werden Experimentdaten abgerufen.                                                                                                                                                                                                                                                                                                                      | `false`  |
  | kcs (*optional*)                 | `boolean` | Bei true wird der Kameleoon Conversion Score (KCS) abgerufen. Erfordert das [AI Predictive Targeting Add-on](/user-manual/ai-predictive-targeting/target-users-based-on-likelihood-to-convert)                                                                                                                                                                  | `false`  |
  | visitorCode (*optional*)         | `boolean` | Bei true ruft Kameleoon den `visitorCode` aus dem letzten Besuch ab und verwendet ihn für den aktuellen Besuch. Dies ist notwendig, um sicherzustellen, dass der Besucher, identifiziert durch seinen `visitorCode`, bei [geräteübergreifenden Experimenten](/developer-docs/cross-device-experimentation) über Besuche hinweg immer dieselbe variation erhält. | `true`   |
  | personalization (*optional*)     | `boolean` | Bei true werden Personalisierungsdaten abgerufen. Dies ist für die Personalisierungsbedingung erforderlich.                                                                                                                                                                                                                                                     | `false`  |
  | cbs (*optional*)                 | `boolean` | Bei true werden Contextual-Bandit-Score-Daten abgerufen.                                                                                                                                                                                                                                                                                                        | `false`  |
</Note>

#### getVisitorWarehouseAudience()

* 🔄 *Führt eine asynchrone Anfrage aus*

Ruft alle Audience-Daten ab, die mit dem Besucher in Ihrem Data Warehouse verknüpft sind. Der optionale Parameter `warehouseKey` ist normalerweise Ihre interne User-ID. Der Parameter `customDataIndex` entspricht der Kameleoon Custom Data, die Kameleoon zur Ansprache Ihrer Besucher verwendet. Weitere Details finden Sie in der [Warehouse-Targeting-Dokumentation](/user-manual/integrations/data-warehouses/bigquery/use-bigquery-as-a-source-audience-targeting).

<Warning>
  Da ein Serveraufruf erforderlich ist, ist dieser Mechanismus asynchron. Daher sollten Sie entweder:

  * Einen `completion`-Callback als Argument für die Methode bereitstellen, um sicherzustellen, dass Sie benachrichtigt werden, wenn die Daten erfolgreich abgerufen und dem Besucher hinzugefügt wurden.
  * Coroutinen für die asynchrone Behandlung verwenden.

  Es wird empfohlen, nur auf fehlgeschlagene Ergebnisse zu prüfen. Bei Bedarf kann jedoch überprüft werden, dass die Daten dem Besucher hinzugefügt wurden und für Targeting-Zwecke verfügbar sind (oder zum Debuggen, obwohl die Verwendung von [Logging](#logging) für das Debuggen besser geeignet ist).
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    kameleoonClient.getVisitorWarehouseAudience(customDataIndex, result -> {
        if (result.isSuccess()) {
            // Due to method called before this callback, data was automatically added to the visitor.
        } else {
            Exception exception = result.failure();
            // The request failed due to an exception.
        }
    });

    // If you need to specify warehouse key
    kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex, result -> {
        // Due to method called before this callback, data was automatically added to the visitor,
        // but you can evaluate the added data if necessary.
        try {
            CustomData data = result.getOrThrow();
        } catch (Exception exception) {
            // The request failed due to an exception.
        }
    });
    ```

    ##### Argumente

    | Name                             | Typ                                       | Beschreibung                                                                                                          | Standard |
    | -------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------- |
    | warehouseKey (*optional*)        | `String`                                  | Ein eindeutiger Schlüssel zur Identifizierung der Warehouse-Daten (normalerweise Ihre interne User-ID).               | `null`   |
    | customDataIndex (*erforderlich*) | `int`                                     | Eine Ganzzahl, die den Custom-Data-Index darstellt, den Sie zur Ansprache Ihrer BigQuery-Audiences verwenden möchten. |          |
    | completion (*erforderlich*)      | `ResultCompletion<CustomData, Exception>` | Der Callback, der die empfangenen Daten verarbeitet.                                                                  |          |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    kameleoonClient.getVisitorWarehouseAudience(customDataIndex) { result ->
        if (result.isSuccess) {
            // Due to method called before this callback, data was automatically added to the visitor.
        } else {
            val exception = result.failure()
            // The request failed due to an exception.
        }
    }

    // If you need to specify warehouse key
    kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex) { result ->
        // As a result of the method before this callback is called, data was automatically added to the visitor
        // but you can evaluate the added data if you need to check it.
        try {
            val data = result.getOrThrow()
        } catch (e: Exception) {
            // The request failed due to an exception.
        }
    }
    ```

    ##### Argumente

    | Name                             | Typ                                       | Beschreibung                                                                                                          | Standard |
    | -------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------- |
    | warehouseKey (*optional*)        | `String`                                  | Ein eindeutiger Schlüssel zur Identifizierung der Warehouse-Daten (normalerweise Ihre interne User-ID).               | `null`   |
    | customDataIndex (*erforderlich*) | `Int`                                     | Eine Ganzzahl, die den Custom-Data-Index darstellt, den Sie zur Ansprache Ihrer BigQuery-Audiences verwenden möchten. |          |
    | completion (*erforderlich*)      | `ResultCompletion<CustomData, Exception>` | Der Callback, der die empfangenen Daten verarbeitet.                                                                  |          |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Ein häufiger Fehler ist die Verwendung von Suspending-Funktionen innerhalb von `mapCatching`, `runCatching` oder einem `try-catch`-Block, ohne `CancellationException` ordnungsgemäß erneut auszulösen, was die Coroutine-Abbruchlogik stören kann. Um ein korrektes Verhalten sicherzustellen, vermeiden Sie das Aufrufen von Suspend-Funktionen innerhalb dieser Blöcke.
    </Warning>

    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    viewModelScope.launch {
        // As a result of the method call, the data was automatically added to the visitor.
        kameleoonClient.getVisitorWarehouseAudience(customDataIndex = customDataIndex) ?: return@launch
    }

    // If you need to specify warehouse key
    viewModelScope.launch {
        // As a result of the method call, the data was automatically added to the visitor.
        kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex)
            .onSuccess { customData ->
                // But you can evaluate the added data if you need to check it.
            }
            .onFailure { ex ->
                // The request failed due to an exception.
            }
    }
    ```

    ##### Argumente

    | Name                             | Typ      | Beschreibung                                                                                                          | Standard |
    | -------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | -------- |
    | warehouseKey (*optional*)        | `String` | Ein eindeutiger Schlüssel zur Identifizierung der Warehouse-Daten (normalerweise Ihre interne User-ID).               | `null`   |
    | customDataIndex (*erforderlich*) | `Int`    | Eine Ganzzahl, die den Custom-Data-Index darstellt, den Sie zur Ansprache Ihrer BigQuery-Audiences verwenden möchten. |          |

    ##### Rückgabewert

    | Typ                  | Beschreibung                                                                                                  |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<CustomData>` | Ein Kotlin-`Result`, das entweder den abgerufenen Wert (`CustomData`) oder die aufgetretene Ausnahme enthält. |
  </Tab>
</Tabs>

#### setLegalConsent()

Sie müssen diese Methode verwenden, um anzugeben, ob der Besucher seine rechtliche Zustimmung zur Verwendung seiner personenbezogenen Daten gegeben hat. Das Setzen des Parameters `legalConsent` auf `false` schränkt die Arten von Daten ein, die Sie in Tracking-Anfragen einbeziehen können. Diese Methode hilft Ihnen, rechtliche und regulatorische Anforderungen einzuhalten und gleichzeitig Besucherdaten verantwortungsvoll zu verwalten. Weitere Informationen zu personenbezogenen Daten finden Sie in der [Consent-Management-Richtlinie](/user-manual/project-management/consent-management-policy).

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.setLegalConsent(true);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.setLegalConsent(true)
    ```
  </Tab>
</Tabs>

##### Argumente

| Name         | Typ     | Beschreibung                                                                                                                                                                                                                                                                              |
| ------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| legalConsent | boolean | Ein boolescher Wert, der den Status der rechtlichen Zustimmung darstellt. `true` zeigt an, dass der Besucher seine rechtliche Zustimmung gegeben hat, `false` zeigt an, dass der Besucher nie eine rechtliche Zustimmung erteilt oder diese widerrufen hat. Dieses Feld ist erforderlich. |

### Datentypen

Dieser Abschnitt listet die von Kameleoon unterstützten `com.Kameleoon.Data`-Typen auf. Es werden mehrere Standarddatentypen bereitgestellt, sowie der Typ `CustomData` zur Definition benutzerdefinierter Datentypen.

#### Conversion

Der hier gespeicherte `Conversion`-Datensatz kann verwendet werden, um Experiment- und Personalisierungsberichte nach einem beliebigen damit verknüpften Ziel zu filtern.

<Tip>
  * Jeder Besucher kann mehrere `Conversion`-Objekte haben.
  * Sie finden die `goalId` in der Kameleoon-App.
</Tip>

| Name                    | Typ             | Beschreibung                                       | Standard            |
| ----------------------- | --------------- | -------------------------------------------------- | ------------------- |
| goalId (*erforderlich*) | `int`           | ID des Ziels.                                      |                     |
| revenue (*optional*)    | `float`         | Umsatz der Konversion                              | `0`                 |
| negative (*optional*)   | `boolean`       | Definiert, ob der Umsatz positiv oder negativ ist. | `false`             |
| metadata (*optional*)   | `CustomData...` | Metadaten der Konversion.                          | `new CustomData[0]` |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new Conversion(32, 10f));

    kameleoonClient.addData(new Conversion(33, 0f, true));

    kameleoonClient.addData(
        new Conversion(34, 5f, new CustomData(3, "metadata1", "md2"), new CustomData(5, "md3"))
    );
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Conversion(32, 10f))

    kameleoonClient.addData(Conversion(33, 0f, true))

    kameleoonClient.addData(
        Conversion(34, 5f, CustomData(3, "metadata1", "md2"), CustomData(5, "md3"))
    )
    ```
  </Tab>
</Tabs>

#### Device

<Note>
  Seit Android SDK `4.13.0` wird das `Device` automatisch basierend auf dem [`android.content.Context`](https://developer.android.com/reference/android/content/Context) erkannt. Sie können es jedoch bei Bedarf weiterhin manuell überschreiben.
</Note>

Speichert Informationen über das Gerät des Benutzers.

| Name                    | Typ       | Beschreibung                                          |
| ----------------------- | --------- | ----------------------------------------------------- |
| device (*erforderlich*) | `Devices` | Liste der Geräte: **phone**, **tablet**, **desktop**. |

<Tabs defaultTabIndex={0}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(Device.tablet());
    ```
  </Tab>
</Tabs>

#### Geolocation

`Geolocation` enthält die Geolocation-Details des Besuchers.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new Geolocation("France", "Île-de-France", "Paris"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Geolocation("France", "Île-de-France", "Paris"))
    ```
  </Tab>
</Tabs>

| Name                     | Typ                   | Beschreibung                                                                                                       |
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------ |
| country (*erforderlich*) | `String`              | Das Land des Besuchers.                                                                                            |
| region (*optional*)      | <nobr>`String`</nobr> | Die Region des Besuchers.                                                                                          |
| city (*optional*)        | <nobr>`String`</nobr> | Die Stadt des Besuchers.                                                                                           |
| postalCode (*optional*)  | <nobr>`String`</nobr> | Die Postleitzahl des Besuchers.                                                                                    |
| latitude (*optional*)    | `float`               | Die Breitengrad-Koordinate, die den Standort des Besuchers darstellt. Die Koordinatenzahl stellt Dezimalgrade dar. |
| longitude (*optional*)   | `float`               | Die Längengrad-Koordinate, die den Standort des Besuchers darstellt. Die Koordinatenzahl stellt Dezimalgrade dar.  |

<Tip>
  * Jeder Besucher kann nur eine `Geolocation` haben. Das Hinzufügen einer zweiten `Geolocation` überschreibt die erste.
</Tip>

#### CustomData

Definieren Sie Ihre eigenen benutzerdefinierten Datentypen in der Kameleoon-App oder der Data API und verwenden Sie sie aus dem SDK.

| Name                        | Typ                              | Beschreibung                                                                                                                                                                                            | Standard |
| --------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| index/name (*erforderlich*) | `int`/`String`                   | Index oder Name der Custom Data. **Entweder `index` oder `name` muss angegeben werden**, um die Daten zu identifizieren.                                                                                |          |
| values (*erforderlich*)     | `String...`/`Collection<String>` | Werte der zu speichernden Custom Data.                                                                                                                                                                  |          |
| overwrite (*optional*)      | `boolean`                        | Flag, um explizit zu steuern, wie die Werte gespeichert werden und wie sie in Berichten erscheinen. [Mehr dazu](/developer-docs/custom-data#default-logic-when-overwrite-parameter-is-false-or-omitted) | `true`   |

<Note>
  * Der Index der Custom Data ist auf der Seite **Custom Data Konfiguration** der Kameleoon-App verfügbar. Achtung: Dieser Index beginnt bei 0, sodass die erste Custom Data, die Sie für eine bestimmte Site erstellen, den Index 0 hat, nicht 1.
  * Das Hinzufügen einer `CustomData`-Instanz, die mit einem Namen erstellt wurde, wenn die Konfiguration der SDK-Instanz nicht aktuell ist oder der Name nicht registriert ist, führt dazu, dass die Daten ignoriert werden.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new CustomData(1, "value"));

    // With several values
    kameleoonClient.addData(new CustomData(1, "value1", "value2"));

    // To set the 'overwrite' flag to false
    kameleoonClient.addData(new CustomData(1, false, "value"));

    // To use a name instead of the index
    kameleoonClient.addData(new CustomData("my-custom-data", "value"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(CustomData(1, "value"))

    // With several values
    kameleoonClient.addData(CustomData(1, "value1", "value2"))

    // To set the 'overwrite' flag to false
    kameleoonClient.addData(CustomData(1, false, "value"))

    // To use a name instead of the index
    kameleoonClient.addData(CustomData("my-custom-data", "value"))
    ```
  </Tab>
</Tabs>

### Rückgabetypen

#### DataFile

Die `DataFile` enthält die Details der SDK-Konfiguration.

Sie kann bei Bedarf um zusätzliche Informationen erweitert werden, wenn Kunden dies wünschen. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name         | Typ                        | Beschreibung                                                                                    |
| ------------ | -------------------------- | ----------------------------------------------------------------------------------------------- |
| featureFlags | `Map<String, FeatureFlag>` | Eine Map von [`FeatureFlag`](#featureflag)-Objekten, geschlüsselt nach feature flag-Schlüsseln. |
| dateModified | `long`                     | Der Zeitstempel (in Millisekunden), der angibt, wann die `DataFile` zuletzt geändert wurde.     |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieves the map of feature flags from the DataFile.
    // The map is keyed by feature flag identifiers, with each value being a FeatureFlag object.
    Map<String, FeatureFlag> featureFlags = dataFile.getFeatureFlags();

    // Retrieves the last modification timestamp of the DataFile.
    // The value is a long representing milliseconds since the Unix epoch.
    long dateModified = dataFile.getDateModified();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieves the map of feature flags from the DataFile.
    // The map is keyed by feature flag identifiers, with each value being a FeatureFlag object.
    val featureFlags = dataFile.featureFlags

    // Retrieves the last modification timestamp of the DataFile.
    // The value is a long representing milliseconds since the Unix epoch.
    val dateModified = dataFile.dateModified
    ```
  </Tab>
</Tabs>

#### FeatureFlag

Der `FeatureFlag` stellt eine Reihe von Eigenschaften dar, die einen feature flag selbst definieren – zum Beispiel seine [`Variations`](#variation), [`Rules`](#rule), den Umgebungsstatus und weitere zugehörige Details.

Er kann bei Bedarf um zusätzliche Informationen erweitert werden, wenn Kunden dies wünschen. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name                | Typ                      | Beschreibung                                                               |
| ------------------- | ------------------------ | -------------------------------------------------------------------------- |
| environmentEnabled  | `boolean`                | Gibt an, ob der feature flag in der aktuellen Umgebung aktiviert ist.      |
| defaultVariationKey | `String`                 | Der Schlüssel der mit dem feature flag verknüpften Standard-variation.     |
| variations          | `Map<String, Variation>` | Eine Map von `Variation`-Objekten, geschlüsselt nach variation-Schlüsseln. |
| rules               | `List<Rule>`             | Eine Liste von `Rule`-Objekten                                             |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Check whether the feature flag is enabled in the current environment
    boolean isEnvironmentEnabled = featureFlag.isEnvironmentEnabled();

    // Retrieve the key of the default variation
    String defaultVariationKey = featureFlag.getDefaultVariationKey();

    // Retrieve the default variation object
    Variation defaultVariation = featureFlag.getDefaultVariation();

    // Retrieve all variations of the feature flag as a map (key = variation key, value = Variation object)
    Map<String, Variation> variations = featureFlag.getVariations();

    // Retrieve all targeting rules associated with the feature flag
    List<Rule> rules = featureFlag.getRules();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Check whether the feature flag is enabled in the current environment
    val isEnvironmentEnabled = featureFlag.isEnvironmentEnabled

    // Retrieve the key of the default variation
    val defaultVariationKey = featureFlag.defaultVariationKey

    // Retrieve the default variation object
    val defaultVariation = featureFlag.defaultVariation

    // Retrieve all variations of the feature flag as a map (key = variation key, value = Variation object)
    val variations = featureFlag.variations

    // Retrieve all targeting rules associated with the feature flag
    val rules = featureFlag.rules
    ```
  </Tab>
</Tabs>

#### Rule

Die `Rule` stellt eine Reihe von Eigenschaften dar, die eine Regel selbst definieren – zum Beispiel ihre [`Variations`](#variation).

Sie kann bei Bedarf um zusätzliche Informationen erweitert werden, wenn Kunden dies wünschen. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name       | Typ                      | Beschreibung                                                               |
| ---------- | ------------------------ | -------------------------------------------------------------------------- |
| variations | `Map<String, Variation>` | Eine Map von `Variation`-Objekten, geschlüsselt nach variation-Schlüsseln. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
    Map<String, Variation> variations = rule.getVariations();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
    val variations = rule.variations
    ```
  </Tab>
</Tabs>

#### Variation

`Variation` enthält Informationen über die dem Besucher zugewiesene variation (oder die Standard-variation, wenn keine spezifische Zuweisung existiert).

| Name         | Typ                     | Beschreibung                                                                                                                                                                |
| ------------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name         | `String`                | Der Name der variation.                                                                                                                                                     |
| key          | `String`                | Der eindeutige Schlüssel, der die variation identifiziert.                                                                                                                  |
| id           | `Integer`               | Die ID der zugewiesenen variation (oder `null`, wenn es sich um die Standard-variation handelt).                                                                            |
| experimentId | `Integer`               | Die ID des mit der variation verknüpften Experiments (oder `null`, wenn Standard).                                                                                          |
| variables    | `Map<String, Variable>` | Eine Map, die die Variablen der zugewiesenen variation enthält, geschlüsselt nach Variablennamen. Dies kann eine leere Sammlung sein, wenn keine Variablen zugeordnet sind. |

<Note>
  * Das `Variation`-Objekt liefert Details über die zugewiesene variation und das zugehörige Experiment, während das [`Variable`](#variable)-Objekt spezifische Details zu jeder Variable innerhalb einer variation enthält.
  * Stellen Sie sicher, dass Ihr Code den Fall behandelt, in dem `id` oder `experimentId` `null` sein kann, was auf eine Standard-variation hinweist.
  * Die `variables`-Map kann leer sein, wenn keine Variablen mit der variation verknüpft sind.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieving the variation name
    String variationName = variation.getName();

    // Retrieving the variation key
    String variationKey = variation.getKey();

    // Retrieving the variation id
    Integer variationId = variation.getId();

    // Retrieving the experiment id
    Integer experimentId = variation.getExperimentId();

    // Retrieving the variables map
    Map<String, Variable> variables = variation.getVariables();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieving the variation name
    val variationName = variation.name

    // Retrieving the variation key
    val variationKey = variation.key

    // Retrieving the variation id
    val variationId = variation.id

    // Retrieving the experiment id
    val experimentId = variation.experimentId

    // Retrieving the variables map
    val variables = variation.variables
    ```
  </Tab>
</Tabs>

#### Variable

`Variable` enthält Informationen über eine Variable, die mit der zugewiesenen variation verknüpft ist.

| Name  | Typ      | Beschreibung                                                                                                                                                      |
| ----- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| key   | `String` | Der eindeutige Schlüssel, der die Variable identifiziert.                                                                                                         |
| type  | `String` | Der Typ der Variable. Mögliche Werte: **BOOLEAN**, **NUMBER**, **STRING**, **JSON**.                                                                              |
| value | `Object` | Der Wert der Variable, der einen der folgenden Typen haben kann: **boolean**, **int**, **long**, **double**, **String**, **JSONObject**, **JSONArray**, **null**. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieving the variables map
    Map<String, Variable> variables = variation.getVariables();

    // Variable type can be retrieved for further processing
    String type = variables.get("isDiscount").getType();

    // Get the Boolean value of "isDiscount"
    Boolean isDiscount = (Boolean) variables.get("isDiscount").getValue();

    // Get the numeric value of "number" as an Integer
    Integer number = (Integer) variables.get("number").getValue();

    // Get the String value of "title"
    String title = (String) variables.get("title").getValue();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieving the variables map
    val variables = variation.variables

    // Variable type can be retrieved for further processing
    val type = variables["isDiscount"]?.type

    // Get the Boolean value of "isDiscount"
    val isDiscount = variables["isDiscount"]?.value as? Boolean

    // Get the numeric value of "number" as an Integer
    val number = variables.get("number").value as? Int

    // Get the String value of "title"
    val title = variables["title"]?.value as? String
    ```
  </Tab>
</Tabs>

### Veraltete Methoden

<Warning>
  Diese Methoden sind veraltet und werden in der SDK-Version `5.0.0` entfernt.
</Warning>

#### getFeatureVariationKey()

* 📨 *Sendet Tracking-Daten an Kameleoon*

<Note>
  Verwenden Sie stattdessen [`getVariation()`](#getvariation).
</Note>

Verwenden Sie diese Methode, um den feature variation key für einen Besucher abzurufen. Diese Methode benötigt einen `featureKey` als erforderliches Argument, um den variation-Schlüssel für den angegebenen Benutzer abzurufen.

Wenn der Besucher noch nie mit diesem feature flag in Verbindung gebracht wurde, gibt das SDK einen zufällig zugewiesenen variation-Schlüssel zurück (gemäß den feature flag-Regeln). Wenn der Besucher bereits bei diesem feature flag registriert ist, gibt diese Methode den vorherigen variation-Schlüssel zurück. Wenn der Benutzer keiner der Regeln entspricht, wird der Standardwert zurückgegeben, der im Konto Ihres Kunden definiert ist.

Stellen Sie sicher, dass Sie eine ordnungsgemäße Fehlerbehandlung wie im Beispielcode gezeigt einrichten, um potenzielle Ausnahmen abzufangen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";
    String variationKey = "";

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    switch (variationKey) {
        case "on":
            //main variation key is selected for visitorCode
            break;
        case "alternative_variation":
            //alternative variation key
            break;
        default:
            //default variation key
            break;
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var variationKey = ""

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // Exception indicates that the SDK not initialized or the feature toggle is not yet activated on Kameleoon's side. We consider the feature inactive.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    when (variationKey) {
        "on" -> {}
        "alternative_variation" -> {}
        else -> {}
    }
    ```
  </Tab>
</Tabs>

#### getFeatureVariationKey()

* 📨 *Sendet Tracking-Daten an Kameleoon*

<Note>
  Verwenden Sie stattdessen [`getVariation()`](#getvariation).
</Note>

Verwenden Sie diese Methode, um den feature variation key für einen Besucher abzurufen. Diese Methode benötigt einen `featureKey` als erforderliches Argument, um den variation-Schlüssel für den angegebenen Benutzer abzurufen.

Wenn der Besucher noch nie mit diesem feature flag in Verbindung gebracht wurde, gibt das SDK einen zufällig zugewiesenen variation-Schlüssel zurück (gemäß den feature flag-Regeln). Wenn der Besucher bereits bei diesem feature flag registriert ist, gibt diese Methode den vorherigen variation-Schlüssel zurück. Wenn der Benutzer keiner der Regeln entspricht, wird der Standardwert zurückgegeben, der im Konto Ihres Kunden definiert ist.

Stellen Sie sicher, dass Sie eine ordnungsgemäße Fehlerbehandlung wie im Beispielcode gezeigt einrichten, um potenzielle Ausnahmen abzufangen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";
    String variationKey = "";

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    switch (variationKey) {
        case "on":
            //main variation key is selected for visitorCode
            break;
        case "alternative_variation":
            //alternative variation key
            break;
        default:
            //default variation key
            break;
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var variationKey = ""

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // Exception indicates that the SDK not initialized or the feature toggle is not yet activated on Kameleoon's side. We consider the feature inactive.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    when (variationKey) {
        "on" -> {}
        "alternative_variation" -> {}
        else -> {}
    }
    ```
  </Tab>
</Tabs>

#### getActiveFeatures()

<Note>
  * Verwenden Sie stattdessen [`getVariations()`](#getvariations).
  * Hieß zuvor `getFeatureListForVisitorCode` und wurde in der SDK-Version `4.0.0` entfernt.
</Note>

Die Methode `getActiveFeatures` ruft Informationen über die aktiven feature flags ab, die für den Besucher verfügbar sind.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    Map<String, Variation> listActiveFeatureFlags = kameleoonClient.getActiveFeatures();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val listActiveFeatureFlags = kameleoonClient.getActiveFeatures()
    ```
  </Tab>
</Tabs>

##### Rückgabewert

| Typ                      | Beschreibung                                                                                                                                     |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Map<String, Variation>` | Ein Dictionary, das die zugewiesenen variations der aktiven Features unter Verwendung der Schlüssel der entsprechenden aktiven Features enthält. |

#### getFeatureVariable()

* 📨 *Sendet Tracking-Daten an Kameleoon*

<Note>
  Verwenden Sie stattdessen [`getVariation()`](#getvariation).
</Note>

Diese Methode ruft einen Variablenwert eines variation-Schlüssels für einen bestimmten Benutzer ab. Sie benötigt `featureKey` und `variableKey` als erforderliche Argumente.

Wenn der Besucher noch nie mit dem `featureKey` in Verbindung gebracht wurde, gibt das SDK einen zufällig zugewiesenen Variablenwert für den angegebenen variation-Schlüssel zurück (gemäß den feature flag-Regeln). Wenn der Besucher bereits bei diesem feature flag registriert ist, gibt die Methode den Variablenwert für die zuvor registrierte variation zurück. Wenn der Benutzer keiner der Regeln entspricht, wird der Standardwert der Variable zurückgegeben.

Stellen Sie sicher, dass Sie eine ordnungsgemäße Fehlerbehandlung wie im Beispielcode gezeigt einrichten, um potenzielle Ausnahmen abzufangen.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "feature_key";
    String variableKey = "variableKey";

    try {
        Object variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey);
        // your custom code, depending on variableValue
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureVariableNotFound e) {
        // Requested variable not defined in Kameleoon
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment.
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    val variableKey = "var"

    try {
        val variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey)
        // your custom code depending of variableValue
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The error is happened, feature flag isn't found in current configuraiton
    } catch (e: KameleoonException.FeatureVariableNotFound) {
        // Requested variable not defined on Kameleoon's side
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name         | Typ    | Beschreibung                                                                                   |
| ------------ | ------ | ---------------------------------------------------------------------------------------------- |
| featureKey   | String | Schlüssel der Funktion, die Sie einem Benutzer anzeigen möchten. Dieses Feld ist erforderlich. |
| variableName | String | Name der Variable, für die Sie einen Wert abrufen möchten. Dieses Feld ist erforderlich.       |

##### Rückgabewert

| Typ    | Beschreibung                                                                                                                                                                               |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| object | Wert der variation-Variable, der für den angegebenen `visitorCode` für diesen feature flag registriert ist. Gültige Typen: `boolean`, `int`, `double`, `String`, `JSONObject`, `JSONArray` |

##### Ausgelöste Ausnahmen

| Typ                        | Beschreibung                                                                                                                                                                                                                                                                                                                         |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| SDKNotReady                | Ausnahme, die anzeigt, dass das SDK seine Initialisierung noch nicht abgeschlossen hat.                                                                                                                                                                                                                                              |
| FeatureNotFound            | Ausnahme, die anzeigt, dass der angeforderte Feature-Schlüssel in der internen Konfiguration des SDK gefunden wurde. Diese Ausnahme bedeutet normalerweise, dass der feature flag auf der Kameleoon-Seite noch nicht aktiviert wurde (aber der Code, der die Funktion implementiert, bereits in der Anwendung bereitgestellt wurde). |
| FeatureVariableNotFound    | Ausnahme, die anzeigt, dass die angegebene Variable nicht gefunden wurde. Überprüfen Sie, ob der Variablenschlüssel in der Kameleoon-App mit dem in Ihrem Code übereinstimmt.                                                                                                                                                        |
| FeatureEnvironmentDisabled | Ausnahme, die anzeigt, dass der feature flag für die aktuelle Umgebung des Besuchers deaktiviert ist (z. B. production, staging oder development).                                                                                                                                                                                   |

#### getFeatureVariationVariables()

<Note>
  * Verwenden Sie stattdessen [`getVariation()`](#getvariation).
  * Diese Methode hieß zuvor `getFeatureAllVariables` und wurde in der SDK-Version `4.0.0` entfernt.
</Note>

Um alle Variablen einer Funktion abzurufen, rufen Sie diese Methode auf. Sie können Ihre Feature-Variablen in der Kameleoon-App ändern.

Diese Methode nimmt einen Eingabeparameter: `featureKey`. Sie gibt die Daten als Typ `Map<String, Object>` zurück, wie in der Kameleoon-App definiert. Sie löst eine Ausnahme (`FeatureNotFound`) aus, wenn das angeforderte Feature nicht in der internen Konfiguration des SDK gefunden wurde.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "myFeature";
    String variationKey = "variation1";

    try {
        Map<String, Object> variables = kameleoonClient.getFeatureVariationVariables(featureKey, variationKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The feature is not yet activated on Kameleoon's side
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // This is a generic Exception handler which will handle all exceptions.
        System.out.println("Exception occurred");
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "myFeature"
    val variationKey = "variation1"

    try {
        val variables = kameleoonClient.getFeatureVariationVariables(featureKey, variationKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The feature is not yet activated on Kameleoon's side
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // This is a generic Exception handler which will handle all exceptions.
        println("Exception occurred")
    }
    ```
  </Tab>
</Tabs>

##### Argumente

| Name       | Typ    | Beschreibung                                                                           |
| ---------- | ------ | -------------------------------------------------------------------------------------- |
| featureKey | String | Eindeutige Kennung der Funktion, die Sie abrufen müssen. Dieses Feld ist erforderlich. |

##### Rückgabewert

| Typ                  | Beschreibung                                                                                                                                                                                                     |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Map<String,Object>` | Daten, die die mit diesem feature flag verknüpften Variablen darstellen. Werte können `int`, `String`, `boolean`, `JSONObject` oder `JSONArray` sein (abhängig von den in der Web-Oberfläche definierten Typen). |

##### Ausgelöste Ausnahmen

| Typ                        | Beschreibung                                                                                                                                                                                                                      |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SDKNotReady                | Ausnahme, die anzeigt, dass das SDK seine Initialisierung noch nicht abgeschlossen hat.                                                                                                                                           |
| FeatureNotFound            | Ausnahme, die anzeigt, dass das angeforderte Feature nicht in der internen Konfiguration des SDK gefunden wurde. Diese Ausnahme bedeutet normalerweise, dass der feature flag auf der Kameleoon-Seite noch nicht aktiviert wurde. |
| FeatureVariableNotFound    | Ausnahme, die anzeigt, dass die angegebene Variable nicht gefunden wurde. Überprüfen Sie, ob der Variablenschlüssel in der Kameleoon-App mit dem Schlüssel in Ihrem Code übereinstimmt.                                           |
| FeatureEnvironmentDisabled | Ausnahme, die anzeigt, dass der feature flag für die aktuelle Umgebung des Besuchers deaktiviert ist (z. B. production, staging oder development).                                                                                |

#### getFeatureList()

<Tip>
  Wenn Sie über alle feature flags iterieren und für jeden [`getVariation()`](#getvariation) aufrufen möchten, verwenden Sie stattdessen die Methode [`getVariations()`](#getvariations).
</Tip>

Gibt eine Liste der feature flag-Schlüssel zurück, die derzeit für das SDK verfügbar sind.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    List<String> allFeatureFlagListId = kameleoonClient.getFeatureList();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val allFeatureFlagListId = kameleoonClient.getFeatureList()
    ```
  </Tab>
</Tabs>

##### Rückgabewert

| Typ            | Beschreibung                     |
| -------------- | -------------------------------- |
| `List<String>` | Liste der feature flag-Schlüssel |
