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

# C++ SDK

> Integrieren Sie das Kameleoon C++ SDK, um Experimente auszuführen und Feature Flags in C++-Diensten und Web-Backends zu aktivieren.

Die Integration des SDK in Ihre Anwendung ist einfach, und sein Fußabdruck (Speicher- und Netzwerknutzung) ist gering.

**Erste Schritte**: Hilfe für den Einstieg finden Sie im [Entwicklerhandbuch](#entwicklerhandbuch).

**Neueste Version**: `0.8.5`. Versionshinweise finden Sie im [Changelog des C++ SDK](https://github.com/Kameleoon-new/client-cpp/blob/main/CHANGELOG.md) oder im [SDK-Changelog-Index](/de/developer-docs/sdks/versions) für alle SDKs.

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

## Entwicklerhandbuch

Dieses Handbuch soll Ihnen helfen, das C++ SDK schnell zu integrieren und mit der Auswertung von Feature Flags in Ihrer C++-Anwendung zu beginnen.

### Erste Schritte

#### Den C++-Client installieren

Das C++ SDK ist eine C++17-Bibliothek, die auf dem Kameleoon SDK Core aufbaut, einer nativen Shared Library (`libkameleoon_ffi`), die in Rust geschrieben ist und das SDK-Verhalten implementiert. Ihre Anwendung linkt die C++-Bibliothek statisch und lädt die Core-Bibliothek zur Laufzeit.

<Warning>
  Der Kameleoon SDK Core wird für Ihre Zielplattform und -architektur aus dem Quellcode kompiliert. Stellen Sie sicher, dass **Rust** und **Cargo** installiert und im `PATH` Ihres Systems verfügbar sind, und installieren Sie `cbindgen`, das den C-Header der Core-Bibliothek generiert:

  ```bash theme={null}
  cargo install cbindgen --locked
  ```

  Rust und Cargo installieren: [https://rust-lang.org/tools/install](https://rust-lang.org/tools/install)

  Zukünftige Versionen werden vorkompilierte Core-Bibliotheken für gängige Plattformen bereitstellen, um die Installation zu vereinfachen. Die lokale Kompilierung bleibt für Benutzer verfügbar, die lieber aus dem Quellcode bauen möchten.
</Warning>

Anforderungen:

* Ein C++17-Compiler (GCC, Clang oder MSVC) und CMake 3.16 oder höher.
* Rust 1.91 oder höher, Cargo und `cbindgen`, um die SDK-Core-Bibliothek zu bauen (`libkameleoon_ffi.so` unter Linux, `libkameleoon_ffi.dylib` unter macOS, `kameleoon_ffi.dll` mit ihrer Importbibliothek `kameleoon_ffi.dll.lib` unter Windows).

Klonen Sie das [C++ SDK-Repository](https://github.com/Kameleoon-new/client-cpp) und bauen Sie die Core-Bibliothek, dann bauen Sie die C++-Bibliothek dagegen:

```bash theme={null}
git clone https://github.com/Kameleoon-new/client-cpp.git
cd client-cpp

# Builds the SDK Core shared library into target/release
cargo build --locked -p kameleoon-ffi --release

# Builds the C++ library; cbindgen generates the core header during this step
cmake -S cpp/client -B cpp/client/build -DKAMELEOON_CPP_BUILD_TESTS=OFF -DKAMELEOON_CPP_BUILD_EXAMPLES=OFF
cmake --build cpp/client/build
```

Um das SDK in Ihr eigenes CMake-Projekt zu integrieren, fügen Sie das Verzeichnis `cpp/client` mit `add_subdirectory()` hinzu und linken Sie das Target `Kameleoon::CppClient`. Verweisen Sie `KAMELEOON_FFI_LIBRARY` auf die von Ihnen gebaute Core-Bibliothek; der C-Header wird mit `cbindgen` generiert, oder Sie können einen vorhandenen mit `KAMELEOON_FFI_HEADER` übergeben:

```cmake title="CMakeLists.txt" theme={null}
set(KAMELEOON_FFI_LIBRARY "${CMAKE_SOURCE_DIR}/third_party/client-cpp/target/release/libkameleoon_ffi.so" CACHE FILEPATH "")
set(KAMELEOON_CPP_BUILD_TESTS OFF CACHE BOOL "")
set(KAMELEOON_CPP_BUILD_EXAMPLES OFF CACHE BOOL "")

add_subdirectory(third_party/client-cpp/cpp/client)

target_link_libraries(my_app PRIVATE Kameleoon::CppClient)
```

<Note>
  * `libkameleoon_ffi` wird zur Laufzeit geladen: Installieren Sie die Bibliothek an einem Standard-Bibliotheksspeicherort oder liefern Sie sie neben Ihrer ausführbaren Datei aus. Unter Linux und macOS erfordert das Ausliefern neben der ausführbaren Datei einen RPATH von `$ORIGIN` oder `@loader_path` (zum Beispiel `set_target_properties(my_app PROPERTIES INSTALL_RPATH "$ORIGIN")`). Unter Windows kopieren Sie `kameleoon_ffi.dll` neben Ihre Binärdateien.
  * Wenn Sie einen Client erstellen, prüft das SDK, ob die geladene `libkameleoon_ffi` mit der Version übereinstimmt, gegen die es gebaut wurde, und wirft andernfalls eine `KameleoonException` mit `ErrorCode::Internal`. Aktualisieren Sie die C++-Bibliothek und die Core-Bibliothek immer gemeinsam.
  * Alle öffentlichen SDK-Typen befinden sich im Namespace `kameleoon`. Inkludieren Sie `kameleoon/kameleoon.hpp`, um die gesamte öffentliche API zu erhalten.
</Note>

#### Zusätzliche Konfiguration

Erstellen Sie eine JSON-Konfigurationsdatei (zum Beispiel `client-cpp.json`), um Anmeldedaten bereitzustellen und das SDK-Verhalten anzupassen. Sie können auch eine [Beispielkonfigurationsdatei](/assets/developer-docs/sdks/web-sdks/client-configs/client-config.json) herunterladen.

Das C++ SDK kann entweder mit einer JSON-Datei konfiguriert werden, deren Pfad Sie an `KameleoonClientFactory::create()` übergeben, oder indem Sie eine `KameleoonClientConfig`-Struktur direkt im Code befüllen.

Die folgende Tabelle zeigt die verfügbaren Eigenschaften, die Sie festlegen können:

| Schlüssel (Code / Konfigurationsdatei) | Beschreibung | Standardwert |
| - | - | - |
| `client_id` / `clientId` <Badge color="red" size="sm">erforderlich</Badge> | Erforderlich für die Authentifizierung beim Kameleoon-Dienst. Um Ihre `client_id` zu finden, lesen Sie die Dokumentation zu [API credentials](/de/user-manual/account-and-team-management/users-and-teams/api-credentials). | |
| `client_secret` / `clientSecret` <Badge color="red" size="sm">erforderlich</Badge> | Erforderlich für die Authentifizierung beim Kameleoon-Dienst. Um Ihr `client_secret` zu finden, lesen Sie die Dokumentation zu [API credentials](/de/user-manual/account-and-team-management/users-and-teams/api-credentials). | |
| `session_duration_minutes` / `sessionDurationMinutes` <Badge color="green" size="sm">optional</Badge> | Zeitintervall in Minuten, in dem das SDK einen Besucher und seine zugehörigen Daten im Speicher behält. | `30` Minuten |
| `refresh_interval_minutes` / `refreshIntervalMinutes` <Badge color="green" size="sm">optional</Badge> | Intervall in Minuten, das zum Aktualisieren der Konfiguration der aktiven Experimente und Feature Flags verwendet wird. | `60` Minuten |
| `default_timeout_millis` / `defaultTimeoutMillis` <Badge color="green" size="sm">optional</Badge> | Standard-Timeout in Millisekunden für SDK-Netzwerkanfragen. | `10000` Millisekunden |
| `tracking_interval_millis` / `trackingIntervalMillis` <Badge color="green" size="sm">optional</Badge> | Intervall in Millisekunden, das zum Bündeln von Tracking-Anfragen verwendet wird. Werte werden auf den Bereich `[1000, 5000]` begrenzt. | `1000` Millisekunden |
| `environment` / `environment` <Badge color="green" size="sm">optional</Badge> | Umgebung, aus der die Feature-Flag-Konfiguration verwendet werden soll. Der Wert kann `production`, `staging` oder `development` sein. | `std::nullopt` (wird als `production` behandelt) |
| `top_level_domain` / `topLevelDomain` <Badge color="green" size="sm">optional</Badge> | Die aktuelle Top-Level-Domain für Ihre Website. Verwenden Sie das Format `example.com` ohne Protokoll oder Subdomains. | `std::nullopt` |
| `proxy_host` / `proxyHost` <Badge color="green" size="sm">optional</Badge> | Proxy-Host für ausgehende SDK-Aufrufe. Unterstützte Formate: `https://my.prox`, `https://my.prox:4545`, `socks5://192.168.1.1:9000`. | `std::nullopt` |
| `network_domain` / `networkDomain` <Badge color="green" size="sm">optional</Badge> | Benutzerdefinierte Domain, die von SDKs für ausgehende Anfragen verwendet wird, oft für das Proxying. Muss eine gültige Domain sein (z. B. example.com oder sub.example.com). Ungültige Formate verwenden standardmäßig den Kameleoon-Wert. | `std::nullopt` |

#### Den Kameleoon-Client initialisieren

Nachdem Sie das SDK installiert und Ihre Anmeldedaten konfiguriert haben, erstellen Sie einen `KameleoonClient` mithilfe der `KameleoonClientFactory`.

<Tabs>
  <Tab title="Config File">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    using namespace kameleoon;

    KameleoonClient create_client()
    {
        const std::string site_code = "a8st4f59bj";

        KameleoonClient client = KameleoonClientFactory::create(site_code, "/etc/kameleoon/client-cpp.json");
        client.initialize();

        return client;
    }
    ```
  </Tab>

  <Tab title="Code">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    using namespace kameleoon;

    KameleoonClient create_client()
    {
        const std::string site_code = "a8st4f59bj";

        KameleoonClientConfig config{
            .client_id = "<client-id>",                  // mandatory
            .client_secret = "<client-secret>",          // mandatory
            .refresh_interval_minutes = 60,              // optional (60 minutes by default)
            .session_duration_minutes = 30,              // optional (30 minutes by default)
            .default_timeout_millis = 10'000,            // optional (10000 ms by default)
            .tracking_interval_millis = 1'000,           // optional (1000 ms by default)
            .proxy_host = "http://192.168.0.25:8080",    // optional
            .environment = "development",                // optional
            .top_level_domain = ".example.com",          // mandatory if you use hybrid mode (engine or web experiments)
            .network_domain = "example.com",             // optional
        };

        KameleoonClient client = KameleoonClientFactory::create(site_code, config);
        client.initialize();

        return client;
    }
    ```
  </Tab>
</Tabs>

<Note>
  Die Beispiele auf dieser Seite verwenden C++20 [Designated Initializers](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers) (`GetVariationOptions{.track = false}`), um die Konfigurations-, Options- und Datenstrukturen des SDK zu befüllen. Mit einem C++17-Compiler deklarieren Sie stattdessen die Struktur und setzen ihre Felder einzeln.
</Note>

Ein `KameleoonClient` ist das Hauptobjekt, das zum Auswerten von Feature Flags, zum Hinzufügen von Besucherdaten und zum Senden von Tracking-Anfragen verwendet wird.

<Warning>
  * Es wird empfohlen, `KameleoonClient` als Singleton-Objekt zu verwenden, da es als Brücke zwischen Ihrer Anwendung und der Kameleoon-Plattform dient. Es stellt alle erforderlichen Methoden und Eigenschaften bereit, um Experimente effizient auszuführen. `KameleoonClient` ist move-only: Bewahren Sie es an einer Stelle auf und übergeben Sie es per Referenz.
  * Das C++ SDK initialisiert sich asynchron. Sie sollten [`initialize()`](#initialize) aufrufen, bevor Sie sich im Produktionscode auf die Feature-Auswertung verlassen.
  * Jeder SDK-Fehler wird als [`KameleoonException`](#fehlerbehandlung) gemeldet. Umschließen Sie SDK-Aufrufe mit `try`/`catch`-Blöcken.
</Warning>

#### Einen Feature Flag aktivieren

##### Einem Benutzer eine eindeutige ID zuweisen

Um einem Benutzer eine eindeutige ID zuzuweisen, können Sie die Methode [`get_visitor_code()`](#get_visitor_code) verwenden. Wenn ein **Besuchercode** nicht existiert (aus dem Cookie der Request-Header), generiert die Methode eine zufällige eindeutige ID oder verwendet einen `default_visitor_code`, den Sie selbst generiert haben. Die ID wird dann in einem Cookie der Response-Header gesetzt.

Wenn Sie Kameleoon im [Hybridmodus](/de/developer-docs/feature-experimentation/get-started/hybrid-experimentation) verwenden, stellt der Aufruf der Methode `get_visitor_code()` sicher, dass die eindeutige ID (**Besuchercode**) zwischen der Anwendungsdatei `engine.js` (zuvor `kameleoon.js` genannt) und dem SDK geteilt wird.

##### Eine Flag-Konfiguration abrufen

Um einen Feature Flag in Ihrem Code zu implementieren, müssen Sie den Feature Flag zunächst 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 [`get_variation()`](#get_variation) oder [`is_feature_active()`](#is_feature_active) verwenden, um die Konfiguration basierend auf dem `feature_key` abzurufen.

Die Methode `get_variation()` verarbeitet sowohl einfache Feature Flags mit ON/OFF-Zuständen als auch komplexere Flags mit mehreren Variationen. Die Methode ruft die entsprechende Variation für den Benutzer ab, indem sie die Feature-Regeln überprüft, die Variation zuweist und sie basierend auf dem `feature_key` und dem `visitor_code` zurückgibt.

Die Methode `is_feature_active()` 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 Variationen oder Targeting-Optionen.

Wenn Ihr Feature Flag zugehörige Variablen hat (wie spezifische Verhaltensweisen, die mit jeder Variation verbunden sind), ermöglicht Ihnen `get_variation()` auch den Zugriff auf das [`Variation`](#variation)-Objekt, das Details zur zugewiesenen Variation und ihrem zugehörigen Experiment bereitstellt. Diese Methode prüft, ob der Feature Flag den Benutzer anspricht, findet die dem Besucher zugewiesene Variation und speichert sie. Wenn `track=true`, sendet das SDK das Expositions-Event bei der nächsten Tracking-Anfrage an das angegebene Experiment, das automatisch basierend auf dem [`tracking_interval_millis`](#zusätzliche-konfiguration) des SDK ausgelöst wird. Standardmäßig ist dieses Intervall auf 1000 Millisekunden (1 Sekunde) eingestellt.

Mit der Methode `get_variation()` können Sie steuern, ob das SDK den Besucher verfolgt. Wenn `track=false`, werden vom SDK keine Expositions-Events gesendet. Dies ist nützlich, wenn Sie es vorziehen, Daten nicht über das SDK zu verfolgen und sich stattdessen auf clientseitiges Tracking zu verlassen, das z. B. von der Kameleoon-Engine verwaltet wird. Darüber hinaus ist die Einstellung `track=false` hilfreich bei der Verwendung der Methode `get_variations()`, bei der Sie möglicherweise nur die Variationen für alle Flags benötigen, ohne Tracking-Events auszulösen. Wenn Sie mehr darüber erfahren möchten, wie Tracking funktioniert, lesen Sie [diesen Artikel](/de/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics)

##### Datenpunkte hinzufügen, 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 [`add_data()`](#add_data), um diese Datenpunkte zum Profil des Benutzers hinzuzufügen.

Um Datenpunkte abzurufen, die auf anderen Geräten gesammelt wurden, oder um auf vergangene Benutzerdaten zuzugreifen (clientseitig gesammelt bei Verwendung von Kameleoon im Hybridmodus), verwenden Sie die Methode [`get_remote_visitor_data()`](#get_remote_visitor_data). Diese Methode ruft Daten asynchron von den Servern ab. Es ist wichtig, `get_remote_visitor_data()` *vor* dem Abrufen der Variation oder der Überprüfung, ob der Feature Flag aktiv ist, aufzurufen, da das SDK diese Daten benötigen könnte, um einen Benutzer einer bestimmten Variation zuzuweisen.

Um mehr über die verfügbaren Targeting-Bedingungen zu erfahren, lesen Sie den [ausführlichen Artikel zu diesem Thema](/de/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

Darüber hinaus sind die Datenpunkte, die Sie zum Besucherprofil hinzufügen, bei der Analyse Ihrer Experimente verfügbar, sodass Sie Ihre Ergebnisse nach Faktoren wie Gerät und Browser filtern und aufschlüsseln können. Der Kameleoon-Hybridmodus sammelt automatisch eine Vielzahl von Datenpunkten auf der Clientseite, was die Aufschlüsselung Ihrer Ergebnisse anhand dieser vorgesammelten Datenpunkte erleichtert. 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 das hinaus erfassen müssen, was automatisch gesammelt wird, 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 gesammelten Daten zur Analyse an die Kameleoon-Server zu senden.

<Note>
  Um die Genauigkeit Ihrer Ergebnisse sicherzustellen, wird empfohlen, Bots mithilfe des Datentyps [`UserAgent`](#useragent) herauszufiltern.
</Note>

##### Ziel-Conversions verfolgen

Wenn ein Benutzer eine gewünschte Aktion (z. B. einen Kauf) ausführt, wird dies als Conversion erfasst. Um Conversions zu verfolgen, verwenden Sie die Methode [`track_conversion()`](#track_conversion) und geben Sie die erforderlichen Parameter `visitor_code` und `goal_id` an.

Das SDK sendet die Anfrage zur Conversion-Verfolgung zusammen mit der nächsten geplanten Tracking-Anfrage, die in regelmäßigen Intervallen (definiert durch [`tracking_interval_millis`](#zusätzliche-konfiguration)) erfolgt. Wenn Sie die Anfrage sofort senden möchten, verwenden Sie die Methode [`flush_instant()`](#flush).

##### Events an Analyselösungen senden

Um Conversions zu verfolgen und Expositions-Events an Ihre Kundenanalyselösung zu senden, müssen Sie Kameleoon zunächst im [Hybridmodus](/de/developer-docs/feature-experimentation/get-started/hybrid-experimentation) implementieren. Verwenden Sie dann die Methode [`get_engine_tracking_code()`](#get_engine_tracking_code).

Die Methode `get_engine_tracking_code()` ruft den eindeutigen Tracking-Code ab, der zum Senden von Expositions-Events an Ihre Analyselösung erforderlich ist. Mit dieser Methode können Sie Events aufzeichnen und an die gewünschte Analyseplattform senden.

### Fehlerbehandlung

Jeder vom SDK ausgelöste Fehler ist eine `KameleoonException`, sodass ein einziger Handler für diesen Typ jeden SDK-Fehler abfängt. Behandeln Sie einen spezifischen Fehlertyp, wenn Ihre Anwendung auf einen bestimmten Fehler reagieren muss, zum Beispiel um auf Ihr Standardverhalten zurückzufallen, wenn ein Feature Flag nicht in der Konfiguration enthalten oder das SDK noch nicht initialisiert ist. Der Referenzabschnitt jeder Methode listet die Fehler auf, die sie auslösen kann.

`KameleoonException` ist von `std::runtime_error` abgeleitet. Rufen Sie `code()` auf, um den `ErrorCode` zu erhalten, der die Fehler unterscheidet, und `what()`, um die Meldung zu erhalten.

```cpp theme={null}
#include "kameleoon/kameleoon.hpp"

#include <iostream>

using namespace kameleoon;

try {
    Variation variation = client.get_variation(visitor_code, "new_checkout");
} catch (const KameleoonException& error) {
    switch (error.code()) {
    case ErrorCode::FeatureNotFound:
        // The feature flag isn't in the SDK configuration.
        break;
    case ErrorCode::Initialization:
        // The SDK isn't ready yet; fall back to your default behavior.
        break;
    default:
        std::cerr << "Kameleoon error: " << error.what() << "\n";
        break;
    }
}
```

| Fehlercode | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Der Client konnte nicht erstellt werden (leerer Site-Code, fehlende oder nicht lesbare Konfiguration, leere Anmeldedaten), das SDK ist noch nicht initialisiert, oder vor Ablauf des `initialize()`-Timeouts war kein Initialisierungsergebnis verfügbar. |
| `ErrorCode::FeatureNotFound` | Ausnahme, die angibt, dass der angeforderte Feature-Schlüssel in der internen Konfiguration des SDK nicht gefunden wurde. Dies bedeutet in der Regel, dass der Feature Flag in der Kameleoon-App nicht aktiviert ist (aber der Code, der das Feature implementiert, bereits in der Anwendung bereitgestellt ist). |
| `ErrorCode::FeatureExperimentNotFound` | Ausnahme, die angibt, dass die angeforderte Experiment-ID in der internen Konfiguration des SDK nicht gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das der Regel entsprechende Experiment auf der Seite von Kameleoon noch nicht aktiviert wurde. |
| `ErrorCode::FeatureVariationNotFound` | Ausnahme, die angibt, dass der angeforderte Variationsschlüssel (Id) in der internen Konfiguration des SDK nicht gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das der Variation entsprechende Experiment auf der Seite von Kameleoon noch nicht aktiviert wurde. |
| `ErrorCode::FeatureEnvironmentDisabled` | Ausnahme, die angibt, dass der Feature Flag für die aktuelle Umgebung des Besuchers (z. B. production, staging oder development) deaktiviert ist. |
| `ErrorCode::FeatureRuleNotFound` | Die angeforderte Regel wurde in der SDK-Konfiguration nicht gefunden. |
| `ErrorCode::FeatureEvaluationBlocked` | Ausnahme, die angibt, dass die Feature-Auswertung blockiert ist. Der Grund wird in der Fehlermeldung beschrieben. Dies tritt normalerweise aufgrund von DSGVO-Beschränkungen auf, wenn der Besucher keine rechtliche Einwilligung erteilt hat. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::InvalidSimVarCookieFormat` | Zeigt an, dass das Cookie `kameleoonSimulationFFData` fehlerhaft formatiertes JSON enthält und die simulierten Variationen nicht analysiert werden konnten. |
| `ErrorCode::InvalidArgument` | Ein Argument ist ungültig: Eine Zeichenkette ist kein gültiges UTF-8, ein Enum-Wert ist unbekannt, ein Timeout ist null oder negativ, oder eine Eingabe überschreitet die unterstützte Länge. |
| `ErrorCode::Network` | Eine Netzwerkanfrage ist fehlgeschlagen oder der Server hat mit einem nicht erfolgreichen Statuscode geantwortet: der Konfigurationsabruf, eine Anfrage für Remote-Daten oder Remote-Besucherdaten oder eine Warehouse-Audience-Anfrage. Wird auch zurückgegeben, wenn der Client nicht erstellt werden kann, weil `proxy_host` ungültig ist. |
| `ErrorCode::Internal` | Ein unerwarteter interner SDK-Fehler, zum Beispiel eine nicht übereinstimmende `libkameleoon_ffi`-Version, eine Methode, die auf einem moved-from Client aufgerufen wurde, oder ein Variationsschlüssel, der in der Konfiguration fehlt. |

<Note>
  An das SDK übergebene Zeichenketten müssen gültiges UTF-8 sein. Callbacks, die Sie dem SDK bereitstellen (`CookieAccessor`-Overrides, Event-Handler und Logger), dürfen keine Ausnahmen werfen: Jede Ausnahme, die ihnen entkommt, wird an der SDK-Grenze abgefangen und verworfen.
</Note>

<Note>
  SDK-Fehler sind erwartetes Verhalten, keine Abstürze: Ein noch nicht aktivierter Feature Flag, ein SDK, das seine Konfiguration noch lädt, oder ein Netzwerkfehler sind alles normale Zustände. Wenn die Feature-Auswertung fehlschlägt, protokollieren Sie den Fehler und greifen Sie auf Ihr Standardverhalten zurück, damit der Besucher weiterhin ein funktionierendes Erlebnis erhält.
</Note>

### Asynchrone Operationen

Die netzwerkgebundenen Operationen ([`initialize()`](#initialize), [`flush_instant()`](#flush), [`get_remote_data()`](#get_remote_data), [`get_remote_visitor_data()`](#get_remote_visitor_data) und [`get_visitor_warehouse_audience()`](#get_visitor_warehouse_audience)) laufen auf dem eigenen Worker-Thread des SDK. Jede gibt es in drei Formen, sodass Sie die wählen können, die zum aufrufenden Thread passt:

| Form | Beispiel | Verwendung |
| - | - | - |
| Blockierend | `client.initialize(timeout)` | Der Thread kann warten: Start, Shutdown, Batch-Jobs, Tests. |
| Completion | `client.initialize_async(timeout, on_done)` | Sie betreiben eine Ereignisschleife (C++17). Der Aufruf kehrt sofort zurück, und `on_done` erhält das Ergebnis. |
| Awaitable | `co_await client.co_initialize(timeout)` | Sie schreiben C++20-Coroutinen. |

```cpp theme={null}
// Blocking: waits until the data is fetched, throws a KameleoonException on failure.
client.get_remote_visitor_data(visitor_code);

// Completion: returns immediately; `error` is null on success.
client.get_remote_visitor_data_async(visitor_code, {}, [](std::exception_ptr error) {
    if (error) {
        // Rethrow `error` to get the KameleoonException.
        return;
    }
    // The remote data is now available locally.
});

// C++20 coroutine: throws a KameleoonException on failure.
co_await client.co_get_remote_visitor_data(visitor_code);
```

Eine Completion ist eine `Completion<void>` (`std::function<void(std::exception_ptr)>`) oder eine `Completion<T>` (`std::function<void(std::exception_ptr, T)>`) für Operationen, die einen Wert zurückgeben. Das SDK ruft sie genau einmal auf. Sie können die Completion weglassen, um die Operation im Fire-and-forget-Modus auszuführen: Fehler erscheinen dann nur im SDK-Protokoll.

<Warning>
  Completions und Event-Handler laufen normalerweise auf dem SDK-Worker-Thread, aber eine Completion kann auch auf dem aufrufenden Thread laufen, bevor der `*_async`-Aufruf zurückkehrt: zum Beispiel, wenn das SDK schnell fehlschlägt (der Client ist nicht bereit, der Besuchercode ist ungültig) oder wenn `initialize_async()` auf einem bereits initialisierten Client aufgerufen wird. Gehen Sie nicht davon aus, dass eine Completion auf einem bestimmten Thread oder nach der Rückkehr des Aufrufs läuft, und halten Sie über den Aufruf hinweg keine Sperre, die die Completion ebenfalls verwendet. Completions und Event-Handler dürfen nicht blockieren, dürfen keine Ausnahmen werfen und dürfen nicht die blockierende Form einer SDK-Operation aufrufen: Diese wartet auf denselben Worker-Thread und führt zu einem Deadlock. Übergeben Sie das Ergebnis an Ihre eigene Ereignisschleife und schließen Sie die Arbeit dort ab.
</Warning>

<Note>
  C++20 hat keinen eingebauten Coroutine-Task-Typ, daher funktioniert `co_await` nur innerhalb einer Coroutine, deren Promise-Typ das `Awaitable<T>` des SDK akzeptiert (`KAMELEOON_HAS_COROUTINES` wird von `kameleoon/async.hpp` definiert, wenn Coroutinen verfügbar sind). Standardmäßig wird die Coroutine auf dem SDK-Worker-Thread fortgesetzt; rufen Sie `.via(executor)` auf dem Awaitable auf, um stattdessen auf Ihrer eigenen Ereignisschleife fortzufahren. Frameworks mit eigenen Coroutine-Typen, wie Boost.Asio, benötigen einen kleinen Adapter um die Completion-Form; siehe das mit dem SDK ausgelieferte Server-Beispiel.
</Note>

Die Auswertungsmethoden (`get_visitor_code()`, `get_variation()`, `get_variations()`, `is_feature_active()`, `add_data()`, `track_conversion()` und `flush()`) sind synchrone In-Memory-Aufrufe und benötigen nichts davon.

### Verwenden eines benutzerdefinierten Bucketing-Schlüssels

Standardmäßig verwendet Kameleoon eine eindeutige, anonyme Besucher-ID (`visitor_code`), um Benutzer Feature-Flag-Variationen zuzuweisen. Diese ID wird in der Regel auf dem Gerät des Benutzers generiert und gespeichert (in einem Browser-Cookie für client- und serverseitige SDKs und im persistenten 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.

Die Option **Custom Bucketing Key** ermöglicht es Ihnen, dieses Standardverhalten zu überschreiben, indem Sie Ihren eigenen benutzerdefinierten Bezeichner für das Bucketing bereitstellen. Diese Überschreibung stellt sicher, dass die Zuweisungslogik von Kameleoon Ihren angegebenen Schlüssel anstelle des Standard-`visitor_code` verwendet.

#### Anwendungsfälle

Die Verwendung eines benutzerdefinierten Bucketing-Schlüssels ist unerlässlich, um Konsistenz und Genauigkeit bei Ihren Feature-Flag-Zuweisungen aufrechtzuerhalten, insbesondere in diesen 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 einen Bezeichner wie eine `account_id` verwenden. Benutzerdefinierte Bucketing-Schlüssel sind entscheidend für A/B-Tests von Funktionen, die ein ganzes Team oder Unternehmen betreffen.

Durch die Implementierung eines benutzerdefinierten Bucketing-Schlüssels sorgen Sie für eine größere Konsistenz und Genauigkeit Ihrer Experimente, 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 einen bestimmten Bezeichner aus den Daten Ihrer Anwendung zur Verfügung:

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {CustomData(42, {"new_visitor_code"})});
```

* **Bereitstellung des benutzerdefinierten Schlüssels:** Sie stellen Ihren benutzerdefinierten Bezeichner dem Kameleoon SDK über die Methode [`add_data()`](#add_data) zur Verfügung. In dieser Methode übergeben Sie Ihren gewählten benutzerdefinierten Bucketing-Schlüssel als [`CustomData`](#customdata)-Objekt. Hier bezieht sich `new_visitor_code` auf den Bezeichner, den Sie für Ihr Bucketing verwenden möchten (zum Beispiel die neue `user_id` oder `account_id`).

<Warning>
  Damit der benutzerdefinierte Bucketing-Schlüssel korrekt funktioniert, müssen Sie ihn auch für den Feature Flag während des Erstellungs- oder Bearbeitungsprozesses des Flags definieren und konfigurieren. Ohne diese entsprechende Konfiguration wendet das SDK-Bucketing Ihren benutzerdefinierten Schlüssel nicht an. Detaillierte Anweisungen zur Einrichtung in Kameleoon finden Sie in diesem [Artikel](/de/user-manual/experimentation/feature-experimentation/create-and-manage-flags/create-a-feature-flag#erweiterte-flag-einstellungen).
</Warning>

* **Bucketing-Logik:** Sobald Sie einen benutzerdefinierten Bucketing-Schlüssel über die Methode `add_data()` bereitstellen, verwenden alle Hash-Berechnungen zur Zuweisung von Benutzern zu Variationen diesen `new_visitor_code` (Ihren benutzerdefinierten Schlüssel) anstelle des Standard-`visitor_code`. Die Verwendung des `new_visitor_code` bedeutet, dass die Bucketing-Entscheidung von Ihrem benutzerdefinierten Bezeichner abhängt, was konsistente Zuweisungen in verschiedenen Kontexten gewährleistet, in denen dieser Bezeichner vorhanden ist.
* **Datentracking und Analysen:** Es ist wichtig zu beachten, dass, während der `new_visitor_code` (Ihr benutzerdefinierter Schlüssel) für Bucketing-Entscheidungen verwendet wird, das SDK **alle nachfolgenden Daten (zum Beispiel Tracking-Events und Conversions) sendet und mit dem *ursprünglichen* `visitor_code` verknüpft.** Diese Trennung stellt sicher, dass Ihre Analysen die einzelnen Benutzerreisen und -interaktionen im breiteren Kontext Ihres Experiments genau widerspiegeln, selbst wenn Sie das Bucketing auf einer höheren Ebene (zum Beispiel einem Konto) oder über mehrere Geräte/Sitzungen hinweg durchführen. Ihre ursprünglichen Besucherdaten bleiben für eine umfassende Berichterstattung intakt.

#### Technische Anforderungen

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

* Der Schlüssel muss ein `std::string` sein.
* Er muss für die Entität, die Sie bucketen möchten, eindeutig sein (wenn Sie zum Beispiel eine `user_id` verwenden, sollte die ID jedes Benutzers eindeutig sein).
* Der Schlüssel muss dem SDK genau zu dem Zeitpunkt zur Verfügung stehen, an dem es die Feature-Flag-Entscheidung für diesen Benutzer oder diese Anfrage auswertet.

### Targeting-Bedingungen

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

Sie können auch Ihre eigenen [externen Daten verwenden, um Benutzer anzusprechen](/de/developer-docs/apis/data-api-rest/tutorials/storing-and-retrieving-external-data-to-target-users).

### Cross-Device-Experimente

Um Besucher zu unterstützen, die auf eine App von mehreren Geräten zugreifen, ermöglicht Kameleoon die Synchronisierung zuvor gesammelter Besucherdaten über jedes Gerät des Besuchers und die Abstimmung des Besuchsverlaufs zwischen Geräten durch Cross-Device-Experimente. Fallstudien und detaillierte Informationen darüber, wie Kameleoon Daten zwischen Geräten verarbeitet, finden Sie im [Artikel zu Cross-Device-Experimenten](/de/developer-docs/cross-device-experimentation).

#### Synchronisieren von Custom Data zwischen Geräten

Obwohl die Synchronisierung des benutzerdefinierten Mappings Besucherdaten zwischen Geräten abgleicht, ist sie nicht immer erforderlich. Im Folgenden sind zwei Szenarien aufgeführt, in denen die Synchronisierung des benutzerdefinierten Mappings nicht erforderlich ist:

**Gleiche Benutzer-ID auf verschiedenen Geräten**
Wenn Sie dieselbe Benutzer-ID konsistent auf allen Geräten verwenden, handhabt das SDK die Synchronisierung automatisch ohne benutzerdefinierte Mapping-Synchronisierung. Es reicht aus, die Methode `get_remote_visitor_data()` aufzurufen, wenn Sie die zwischen mehreren Geräten gesammelten Daten synchronisieren möchten.

**Multi-Server-Instanzen mit konsistenten IDs**
In komplexen Konfigurationen mit mehreren Servern (zum Beispiel verteilten Serverinstanzen), bei denen dieselbe Benutzer-ID auf allen Servern verfügbar ist, ist die Synchronisierung zwischen Servern (mit `get_remote_visitor_data()`) ohne zusätzliche benutzerdefinierte Mapping-Synchronisierung ausreichend.

Kunden, die zusätzliche Daten benötigen, können in der Beschreibung der Methode [`get_remote_visitor_data()`](#get_remote_visitor_data) weitere Anleitungen finden. Im folgenden Code wird angenommen, dass Sie denselben eindeutigen Bezeichner (in diesem Fall den `visitor_code`, auch bekannt als `userId`) konsistent zwischen den beiden Geräten für eine genaue Datenabfrage verwenden.

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

```cpp title="Device A" theme={null}
// In this example, a Custom data with index `90` was set to "Visitor" scope in Kameleoon.
using namespace kameleoon;

constexpr uint32_t VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90;

client.add_data(visitor_code, {CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, {"your data"})});

client.flush_instant(visitor_code);
```

```cpp title="Device B" theme={null}
// Before working with the data, call the `get_remote_visitor_data` method.
client.get_remote_visitor_data(visitor_code);

// After calling the method, the SDK on Device B will have access to CustomData of Visitor scope defined on Device A.
// So, "your data" will be available for targeting and tracking the visitor.
```

#### Verwenden von Custom Data für die Sitzungszusammenführung

[Cross-Device-Experimente](/de/developer-docs/cross-device-experimentation) ermöglichen die Kombination des Verlaufs eines Besuchers über alle seine Geräte hinweg (Verlaufsabstimmung). Die Verlaufsabstimmung ermöglicht das Zusammenführen verschiedener Besuchersitzungen in eine. Um den Besuchsverlauf abzugleichen, verwenden Sie [`CustomData`](#customdata), um einen eindeutigen Bezeichner für den Besucher bereitzustellen. Weitere Informationen finden Sie in der [speziellen Dokumentation](/de/developer-docs/cross-device-experimentation/#aktivieren-der-cross-device-verlaufsabgleichung).

Nachdem Sie die Cross-Device-Abstimmung aktiviert haben, ruft der Aufruf von [`get_remote_visitor_data()`](#get_remote_visitor_data) mit dem Parameter `userId` alle bekannten Daten für einen bestimmten Benutzer ab.

Sitzungen mit demselben Bezeichner sehen in einem Experiment immer dieselbe Variation. In der Visitor-Ansicht der Ergebnisseiten Ihres Experiments erscheinen diese Sitzungen als ein einziger Besucher.

Die SDK-Konfiguration stellt sicher, dass zugehörige Sitzungen immer dieselbe Variation des Experiments sehen. Es gibt jedoch einige Einschränkungen hinsichtlich der Cross-Device-Variationszuweisung. Die [Dokumentation zu Cross-Device-Experimenten](/de/developer-docs/cross-device-experimentation#kritische-punkte-und-praktische-erkenntnisse) beschreibt diese Einschränkungen.

Folgen Sie der Anleitung [Cross-Device-Verlaufsabstimmung aktivieren](#cross-device-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 der Sitzungszusammenführung hilfreich sein:

* `get_remote_visitor_data()` mit hinzugefügtem `UniqueIdentifier(true)` - um Daten für alle verknüpften Besucher abzurufen.
* [`track_conversion()`](#track_conversion) oder [`flush()`](#flush) mit hinzugefügten `UniqueIdentifier(true)`-Daten - um einige Daten für einen bestimmten Besucher zu verfolgen, der mit einem anderen Besucher verknüpft ist.

<Tip>
  Da die Custom Data, die Sie als Bezeichner verwenden, den **Visitor-Geltungsbereich** erfordert, müssen Sie die [Cross-Device-Custom-Data-Synchronisierung](/de/developer-docs/cross-device-experimentation) verwenden, um den Bezeichner mit der Methode [`get_remote_visitor_data()`](#get_remote_visitor_data) auf jedem Gerät abzurufen.
</Tip>

Hier ist ein Beispiel für die Verwendung von Custom Data für die Sitzungszusammenführung.

```cpp theme={null}
// In this example, 91 represents the Custom Data's index configured as a unique identifier in Kameleoon.
using namespace kameleoon;

constexpr uint32_t MAPPING_INDEX = 91;
const std::string FEATURE_KEY = "ff123";

const std::string anonymous_visitor_code = "anonymous-visitor";
const std::string user_id = "authenticated-user";

// 1. Before the visitor is authenticated

// Retrieve the variation for an unauthenticated visitor.
// Assume anonymousVisitorCode is the randomly generated ID for that visitor.
Variation anonymous_variation = client.get_variation(anonymous_visitor_code, FEATURE_KEY);

// 2. After the visitor is authenticated

// Assume `userId` is the visitor code of the authenticated visitor.
client.add_data(anonymous_visitor_code, {CustomData(MAPPING_INDEX, {user_id})});
client.flush_instant(anonymous_visitor_code);

// Indicate that `userId` is a unique identifier.
client.add_data(user_id, {UniqueIdentifier{true}});

// 3. After the visitor was authorized

// Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
Variation user_variation = client.get_variation(user_id, FEATURE_KEY);
bool is_same_variation = user_variation.key == anonymous_variation.key; // true

// `userId` and `anonymousVisitorCode` are now linked and can be tracked as a single visitor.
client.track_conversion(user_id, 123);

// Additionally, the linked visitors share all fetched previously tracked remote data.
client.get_remote_visitor_data(user_id);
```

In diesem Beispiel hat die App eine Login-Seite. Da die Benutzer-ID zum Zeitpunkt des Logins unbekannt ist, verwendet die App einen anonymen Besucherbezeichner, der von der Methode [`get_visitor_code()`](#get_visitor_code) generiert wird. Nachdem sich der Benutzer angemeldet hat, verknüpft die App den anonymen Besucher mit der Benutzer-ID und verwendet sie als eindeutigen Bezeichner für den Besucher.

### Protokollierung

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

#### Protokollierungsstufen

Das SDK unterstützt die Konfiguration der Begrenzung der Protokollierung durch eine Protokollierungsstufe.

```cpp theme={null}
#include "kameleoon/logging.hpp"

using namespace kameleoon;

// The `None` log level does not allow logging.
KameleoonLogger::set_log_level(LogLevel::None);

// The `Error` log level only allows logging issues that may affect the SDK's primary behaviour.
KameleoonLogger::set_log_level(LogLevel::Error);

// The `Warning` log level allows logging issues which may require attention.
// It extends the `Error` log level.
// The `Warning` log level is the default log level.
KameleoonLogger::set_log_level(LogLevel::Warning);

// The `Info` log level allows logging general information on the SDK's internal processes.
// It extends the `Warning` log level.
KameleoonLogger::set_log_level(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.
KameleoonLogger::set_log_level(LogLevel::Debug);
```

#### Benutzerdefinierte Verarbeitung von Protokollen

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

<Note>
  Das SDK begrenzt die Protokollierung nach Protokollierungsstufe getrennt von der Logik zur Protokollverarbeitung.
</Note>

```cpp theme={null}
#include "kameleoon/logging.hpp"

#include <spdlog/spdlog.h>

using namespace kameleoon;

// Log level filtering is applied separately from log handling logic.
// The custom logger will only receive logs that meet or exceed the specified log level.
// Ensure the log level is set correctly.
KameleoonLogger::set_log_level(LogLevel::Debug); // Optional; defaults to `LogLevel::Warning`.

// The logger is any callable accepting the log level and the message.
// It may be invoked from SDK threads, so it must be thread-safe and must not throw.
KameleoonLogger::set_logger([](LogLevel level, const std::string& message) {
    switch (level) {
    case LogLevel::Error:   spdlog::error(message); break;
    case LogLevel::Warning: spdlog::warn(message); break;
    case LogLevel::Info:    spdlog::info(message); break;
    case LogLevel::Debug:   spdlog::debug(message); break;
    case LogLevel::None:    break;
    }
});

// Passing an empty logger restores the default logger of the SDK, which writes to stdout.
KameleoonLogger::set_logger({});
```

## Referenz

Dies ist die vollständige Referenzdokumentation für das C++ SDK.

### Initialisierung

#### create()

Um das SDK zu verwenden, erstellen Sie einen `KameleoonClient` mit `KameleoonClientFactory::create()`, entweder aus einer `KameleoonClientConfig`-Struktur oder aus einer JSON-Konfigurationsdatei.

Clients werden pro Site-Code und Umgebung zwischengespeichert: Wiederholte `create()`-Aufrufe mit demselben Site-Code und derselben Umgebung geben Clients über dieselbe zugrunde liegende SDK-Instanz zurück, und die Konfiguration des ersten Aufrufs hat Vorrang.

<Tabs>
  <Tab title="create(config struct)">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    using namespace kameleoon;

    KameleoonClientConfig config{
        .client_id = "<client-id>",                  // mandatory
        .client_secret = "<client-secret>",          // mandatory
        .refresh_interval_minutes = 60,              // optional (60 minutes by default)
        .session_duration_minutes = 30,              // optional (30 minutes by default)
        .default_timeout_millis = 10'000,            // optional (10000 ms by default)
        .tracking_interval_millis = 1'000,           // optional (1000 ms by default)
        .proxy_host = "http://192.168.0.25:8080",    // optional
        .environment = "development",                // optional
        .top_level_domain = ".example.com",          // mandatory if you use hybrid mode (engine or web experiments)
        .network_domain = "example.com",             // optional
    };

    KameleoonClient client = KameleoonClientFactory::create(site_code, config);
    ```

    ##### Parameter

    | Name | Typ | Beschreibung |
    | - | - | - |
    | `site_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutiger Schlüssel des Kameleoon-Projekts, das vom SDK verwendet wird. |
    | `config` <Badge color="red" size="sm">erforderlich</Badge> | `KameleoonClientConfig` | SDK-Konfigurationsstruktur. |
  </Tab>

  <Tab title="create(config file)">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    using namespace kameleoon;

    KameleoonClient client = KameleoonClientFactory::create("a8st4f59bj", "/etc/kameleoon/client-cpp.json");
    ```

    ##### Parameter

    | Name | Typ | Beschreibung |
    | - | - | - |
    | `site_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutiger Schlüssel des Kameleoon-Projekts, das vom SDK verwendet wird. |
    | `config_path` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Pfad zur JSON-Konfigurationsdatei. |
  </Tab>
</Tabs>

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `KameleoonClient` | Eine Client-Instanz. Der Client ist erst bereit, Feature Flags auszuwerten, wenn [`initialize()`](#initialize) abgeschlossen ist. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Der Site-Code ist leer, `client_id` oder `client_secret` ist leer, oder die Konfigurationsdatei kann nicht gelesen oder geparst werden. Die Fehlermeldung nennt die genaue Ursache. |
| `ErrorCode::Internal` | Die geladene `libkameleoon_ffi`-Bibliothek entspricht nicht der Version, mit der das SDK erstellt wurde. |

#### initialize()

Verwenden Sie `initialize()`, wenn Ihre App warten soll, bis der Kameleoon-Client die Initialisierung abgeschlossen hat, bevor sie Feature Flags auswertet.

Der Aufruf gibt das Ergebnis des Konfigurationsabrufs zurück: Er wird erfolgreich abgeschlossen, wenn der Client die Initialisierung beendet, und schlägt fehl, wenn der initiale Konfigurationsabruf fehlschlägt, bevor der Client bereit wird. Hintergrund-Wiederholungen werden nach diesem ersten Fehlschlag fortgesetzt. Sobald eine Wiederholung erfolgreich ist, geben nachfolgende Aufrufe ein erfolgreiches Ergebnis zurück. Wenn vor Ablauf des Timeouts kein Initialisierungsergebnis verfügbar ist, schlägt der Aufruf fehl. Wenn Sie keinen `timeout`-Wert angeben, verwendet das SDK den Standard-Timeout aus [`default_timeout_millis`](#zusätzliche-konfiguration).

<Tip>
  Rufen Sie `initialize()` einmal beim App-Start auf, um zu warten, bis das SDK seine Konfiguration geladen hat oder der Timeout abläuft. Verwenden Sie bei jeder eingehenden Anfrage [`is_ready()`](#is_ready) als nicht blockierenden Schutz, bevor Sie Feature Flags auswerten. Selbst wenn `initialize()` fehlschlägt, wiederholt das SDK den Konfigurationsabruf im Hintergrund, sodass `is_ready()` `true` zurückgibt, sobald eine Wiederholung erfolgreich ist.
</Tip>

```cpp theme={null}
#include <chrono>

// Initializes the client using the configured default timeout (blocking).
client.initialize();

// Initializes the client with a custom timeout of 5 seconds (blocking).
client.initialize(std::chrono::seconds(5));

// Initializes the client without blocking; the completion receives the outcome.
client.initialize_async(std::chrono::seconds(5), [](std::exception_ptr error) {
    if (error) {
        // Initialization failed: rethrow `error` to get the `KameleoonException`.
        return;
    }
    // The client is ready.
});

// C++20 coroutines
co_await client.co_initialize(std::chrono::seconds(5));
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `timeout` <Badge color="green" size="sm">optional</Badge> | `std::optional<std::chrono::milliseconds>` | Die maximale Wartezeit auf ein Initialisierungsergebnis. | `default_timeout_millis` |

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `void` | Kehrt zurück, sobald das SDK bereit ist. Löst eine `KameleoonException` aus, wenn der initiale Konfigurationsabruf fehlschlägt oder vor Ablauf des Timeouts kein Initialisierungsergebnis verfügbar ist. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Vor Ablauf des Timeouts war kein Initialisierungsergebnis verfügbar. |
| `ErrorCode::Network` | Der initiale Abruf der Konfiguration ist aufgrund eines Netzwerkfehlers oder eines unerwarteten HTTP-Status fehlgeschlagen. Das SDK wiederholt den Abruf im Hintergrund, sodass ein späterer Aufruf erfolgreich ist, sobald eine Wiederholung erfolgreich war. |
| `ErrorCode::InvalidArgument` | Der angegebene `timeout` ist null oder negativ. |

#### is\_ready()

`is_ready()` prüft, ob das SDK einsatzbereit ist, was bedeutet, dass seine Konfiguration erfolgreich geladen wurde. Im Gegensatz zu [`initialize()`](#initialize) kehrt diese Methode sofort zurück, ohne zu blockieren oder Fehler auszulösen.

<Tip>
  * Sobald das SDK bereit ist, bleibt es bereit. Wenn eine spätere Konfigurationsaktualisierung fehlschlägt, verwendet das SDK weiterhin die zuvor heruntergeladene Konfiguration und kehrt nicht in einen nicht bereiten Zustand zurück.
  * Rufen Sie `initialize()` einmal beim App-Start auf, um zu warten, bis das SDK seine Konfiguration geladen hat oder der Timeout abläuft. Verwenden Sie bei jeder eingehenden Anfrage [`is_ready()`](#is_ready) als nicht blockierenden Schutz, bevor Sie Feature Flags auswerten. Selbst wenn `initialize()` fehlschlägt, wiederholt das SDK den Konfigurationsabruf im Hintergrund, sodass `is_ready()` `true` zurückgibt, sobald eine Wiederholung erfolgreich ist.
</Tip>

```cpp theme={null}
if (client.is_ready()) {
    // The client is ready
}
```

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `bool` | `true`, wenn das SDK erfolgreich initialisiert wurde; andernfalls `false` (auch während die Initialisierung noch aussteht oder fehlgeschlagen ist). |

#### forget()

Entfernt den zwischengespeicherten SDK-Client, der dem angegebenen `site_code` zugeordnet ist, sodass der nächste `create()`-Aufruf mit demselben Site-Code und derselben Umgebung einen neuen erstellt.

`forget()` gibt nur die Referenz der Factory frei. Jeder für diesen Site-Code erstellte `KameleoonClient` hält die zugrunde liegende SDK-Instanz (und ihren Worker-Thread, das Polling und das Tracking) am Leben, bis er zerstört wird, und ausstehende asynchrone Operationen halten sie am Leben, bis ihre Completions abgeschlossen sind. Um die Hintergrundressourcen freizugeben, rufen Sie `forget()` auf und zerstören Sie alle `KameleoonClient`-Instanzen dieses Site-Codes.

```cpp theme={null}
using namespace kameleoon;

// Removes the cached client created for the given site code without an environment
KameleoonClientFactory::forget("a8st4f59bj");

// Removes the cached client for the given site code and environment
KameleoonClientFactory::forget("a8st4f59bj", "production");
```

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `site_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Kameleoon-Projekts. |
| `environment` <Badge color="green" size="sm">optional</Badge> | `std::string` | Umgebung, mit der der Client erstellt wurde. Ein Client, der mit einer `environment` erstellt wurde, wird nur entfernt, wenn hier derselbe Wert übergeben wird. |

### Feature Flags und Variationen

#### is\_feature\_active()

* 📨 *Sendet Tracking-Daten an Kameleoon (abhängig von der Option `track`)*

Bestimmt, ob ein Feature Flag für einen bestimmten Benutzer aktiv ist.

Wenn der Besucher noch nicht für diesen Feature Flag ausgewertet wurde, wertet das SDK die Targeting-Regeln aus und gibt das Ergebnis zurück. Wenn der Besucher bereits eine gespeicherte Auswertung für das Feature hat, verwendet das SDK das vorhandene Ergebnis wieder, um die Konsistenz zu gewährleisten.

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

  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 auf `false`, wenn Sie diese Methoden aufrufen, bevor Sie Besucher aussetzen.

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

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

<Warning>
  Die Methode `is_feature_active()` wertet die ausgelieferte Variante aus, nicht den Master-Flag-Status. Wenn Sie Regeln ausschließen, verwendet die Methode den Standardstatus **Then, for everyone else serve**. Wenn Sie für diesen Standardstatus **Off** auswählen, gibt die Methode immer `false` zurück, auch wenn der Master-Feature-Flag auf **On** steht.
</Warning>

```cpp theme={null}
using namespace kameleoon;

const std::string feature_key = "new_checkout";

// Evaluates the feature flag and sends tracking data (default behavior)
bool active = client.is_feature_active(visitor_code, feature_key);

// Evaluates the feature flag without sending tracking data
bool active_without_tracking = client.is_feature_active(
    visitor_code, feature_key, IsFeatureActiveOptions{.track = false});
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Benutzers. | |
| `feature_key` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Schlüssel des Features, das für den Benutzer ausgewertet werden soll. | |
| `options` <Badge color="green" size="sm">optional</Badge> | `IsFeatureActiveOptions` | Optionsstruktur mit einem einzelnen Feld `track` (`bool`), das das Tracking der Feature-Auswertung aktiviert oder deaktiviert. | `track = true` |

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `bool` | Gibt an, ob der Feature Flag für den angegebenen `visitor_code` aktiv ist. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::FeatureNotFound` | Ausnahme, die angibt, dass der angeforderte Feature-Schlüssel in der internen Konfiguration des SDK nicht gefunden wurde. Dies bedeutet in der Regel, dass der Feature Flag in der Kameleoon-App nicht aktiviert ist (aber der Code, der das Feature implementiert, bereits in der Anwendung bereitgestellt ist). |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

#### get\_variation()

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

Ruft die einem bestimmten Besucher für einen bestimmten Feature Flag zugewiesene [`Variation`](#variation) ab.

Diese Methode nimmt `visitor_code` und `feature_key` als obligatorische Argumente entgegen. Das Argument `track` ist optional und standardmäßig `true`.

Sie gibt die dem Besucher zugewiesene `Variation` zurück. Wenn der Besucher mit keinen Feature-Flag-Regeln 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 Standardvariation bezieht sich auf die Variation, die einem Besucher zugewiesen wird, wenn er keiner vordefinierten Delivery-Regel für einen Feature Flag entspricht. Mit anderen Worten, es ist die Fallback-Variation, die auf alle Benutzer angewendet wird, die nicht durch spezifische Regeln angesprochen werden. Sie wird als Variation im Abschnitt „Then, for everyone else..." in einer Management-Oberfläche dargestellt.
</Note>

```cpp theme={null}
using namespace kameleoon;

const std::string feature_key = "new_checkout";

// Retrieves the variation assigned to the visitor (with tracking enabled by default)
Variation variation = client.get_variation(visitor_code, feature_key);

// Retrieves the variation without sending tracking data
Variation variation_without_tracking = client.get_variation(
    visitor_code, feature_key, GetVariationOptions{.track = false});
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. | |
| `feature_key` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Schlüssel des Features, das Sie einem Besucher zugänglich machen möchten. | |
| `track` <Badge color="green" size="sm">optional</Badge> | `bool` | Ein optionaler Parameter zum Aktivieren oder Deaktivieren des Trackings der Feature-Auswertung. | `true` |

<Note>
  Der optionale Parameter `track` wird als Feld `track` einer `GetVariationOptions`-Struktur übergeben.
</Note>

##### Rückgabewert

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

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::FeatureNotFound` | Ausnahme, die angibt, dass der angeforderte Feature-Schlüssel in der internen Konfiguration des SDK nicht gefunden wurde. Dies bedeutet in der Regel, dass der Feature Flag in der Kameleoon-App nicht aktiviert ist (aber der Code, der das Feature implementiert, bereits in der Anwendung bereitgestellt ist). |
| `ErrorCode::FeatureEnvironmentDisabled` | Ausnahme, die angibt, dass der Feature Flag für die aktuelle Umgebung des Besuchers (z. B. production, staging oder development) deaktiviert ist. |
| `ErrorCode::FeatureEvaluationBlocked` | Ausnahme, die angibt, dass die Feature-Auswertung blockiert ist. Der Grund wird in der Fehlermeldung beschrieben. Dies tritt normalerweise aufgrund von DSGVO-Beschränkungen auf, wenn der Besucher keine rechtliche Einwilligung erteilt hat. |

#### get\_variations()

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

Ruft eine Map von [`Variation`](#variation)-Objekten ab, die einem bestimmten Besucher für alle Feature Flags zugewiesen sind.

Diese Methode iteriert über alle verfügbaren Feature Flags und gibt die zugewiesene `Variation` für jeden mit dem angegebenen Besucher verknüpften Flag zurück. Sie nimmt `visitor_code` als obligatorisches Argument entgegen, während `only_active` und `track` optional sind.

* Wenn Sie `only_active` auf `true` setzen, gibt die Methode `get_variations()` Feature-Flag-Variationen nur zurück, wenn der Besucher nicht mit der `off`-Variation gebucketet ist.
* Der Parameter `track` steuert, ob die Methode die Variationszuweisungen verfolgt. Standardmäßig ist er auf `true` gesetzt. Wenn er auf `false` gesetzt ist, verfolgt die Methode keine Variationszuweisungen.

Die zurückgegebene Map besteht aus Feature-Flag-Schlüsseln als Schlüssel und ihren entsprechenden `Variation`s als Werten. Wenn das SDK für einen Feature Flag keine Variation zuweist, gibt die Methode die Standard-`Variation` für diesen Flag zurück.

Implementieren Sie eine ordnungsgemäße Fehlerbehandlung, um potenzielle Ausnahmen zu verwalten.

<Note>
  Die Standardvariation bezieht sich auf die Variation, die einem Besucher zugewiesen wird, wenn er keiner vordefinierten Delivery-Regel für einen Feature Flag entspricht. Mit anderen Worten, es ist die Fallback-Variation, die auf alle Benutzer angewendet wird, die nicht durch spezifische Regeln angesprochen werden. Sie wird als Variation im Abschnitt „Then, for everyone else..." in einer Management-Oberfläche dargestellt.
</Note>

```cpp theme={null}
using namespace kameleoon;

// Retrieves all variations assigned to the visitor (with default options)
std::unordered_map<std::string, Variation> variations = client.get_variations(visitor_code);

// Retrieves only active variations for the visitor
auto only_active_variations = client.get_variations(
    visitor_code, GetVariationsOptions{.only_active = true});

// Retrieves variations without sending tracking data
auto variations_without_tracking = client.get_variations(
    visitor_code, GetVariationsOptions{.track = false});
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. | |
| `only_active` <Badge color="green" size="sm">optional</Badge> | `bool` | Ein optionaler Parameter, der angibt, ob Variationen für aktive (`true`) oder alle (`false`) Feature Flags zurückgegeben werden sollen. | `false` |
| `track` <Badge color="green" size="sm">optional</Badge> | `bool` | Ein optionaler Parameter zum Aktivieren oder Deaktivieren des Trackings der Feature-Auswertung. | `true` |

<Note>
  Die optionalen Parameter `only_active` und `track` werden als Felder einer `GetVariationsOptions`-Struktur übergeben.
</Note>

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `std::unordered_map<std::string, Variation>` | Map, die die zugewiesenen [`Variation`](#variation)-Objekte der Feature Flags unter Verwendung der Schlüssel der entsprechenden Features enthält. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

#### set\_forced\_variation()

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

Wenn Sie eine **erzwungene** Variation festlegen, überschreibt sie die Echtzeit-Auswertungslogik von Kameleoon. Das SDK überspringt Prozesse wie Segmentierung, Targeting-Bedingungen und algorithmische Berechnungen. Um Segmentierungs- und Targeting-Bedingungen während eines Experiments beizubehalten, setzen Sie stattdessen `force_targeting=false`.

<Info>
  **Simulierte** Variationen haben in der Ausführungsreihenfolge immer Vorrang. Wenn eine **simulierte** Variationsberechnung beginnt, verarbeitet das SDK sie zuerst vollständig und schließt sie ab.
</Info>

Kameleoon behandelt eine erzwungene Variation genauso wie eine ausgewertete Variation. Sie wird in der Analytik verfolgt und im Benutzerkontext wie jede ausgewertete Standardvariation gespeichert, um die Konsistenz im Reporting 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 widerstandsfähig bleibt.

<Warning>
  Es ist wichtig, **erzwungene** Variationen von **[simulierten](#get_visitor_code)** Variationen zu unterscheiden:

  * **Erzwungene Variationen**: Sind spezifisch für ein einzelnes Experiment.
  * **Simulierte Variationen**: Beeinflussen das Gesamtergebnis des **Feature Flags**.
</Warning>

```cpp theme={null}
using namespace kameleoon;

const uint32_t experiment_id = 202387;

// Forces the visitor into "variation_2" for the given experiment
client.set_forced_variation(visitor_code, experiment_id, "variation_2");

// Removes any previously forced variation for the visitor in this experiment
client.set_forced_variation(visitor_code, experiment_id, std::nullopt);

// Forces the visitor into "variation_2" with custom options
// In this case, targeting rules are respected (force_targeting = false)
client.set_forced_variation(
    visitor_code, experiment_id, "variation_2", SetForcedVariationOptions{.force_targeting = false});
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. | |
| `experiment_id` <Badge color="red" size="sm">erforderlich</Badge> | `uint32_t` | **Experiment-ID**, die das SDK während des Auswertungsprozesses anspricht und auswählt. | |
| `variation_key` <Badge color="red" size="sm">erforderlich</Badge> | `std::optional<std::string>` | **Variationsschlüssel**, der einer `Variation` entspricht, die das SDK als zurückgegebenen Wert für das Experiment erzwingt. Wenn der Wert `std::nullopt` ist, wird die erzwungene Variation zurückgesetzt. | |
| `force_targeting` <Badge color="green" size="sm">optional</Badge> | `bool` | Gibt an, ob das SDK das Targeting für das Experiment erzwingt und überspringt (`true`) oder es wie im Standardauswertungsprozess anwendet (`false`). | `true` |

<Note>
  Der optionale Parameter `force_targeting` wird als Feld `force_targeting` einer `SetForcedVariationOptions`-Struktur übergeben.
</Note>

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::FeatureExperimentNotFound` | Ausnahme, die angibt, dass die angeforderte Experiment-ID in der internen Konfiguration des SDK nicht gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das der Regel entsprechende Experiment auf der Seite von Kameleoon noch nicht aktiviert wurde. |
| `ErrorCode::FeatureVariationNotFound` | Ausnahme, die angibt, dass der angeforderte Variationsschlüssel (Id) in der internen Konfiguration des SDK nicht gefunden wurde. Dies ist normalerweise normal und bedeutet, dass das der Variation entsprechende Experiment auf der Seite von Kameleoon noch nicht aktiviert wurde. |

#### evaluate\_audiences()

* 📨 *Sendet Tracking-Daten an Kameleoon*

Diese Methode wertet Besucher anhand aller verfügbaren Audiences-Explorer-Segmente aus und verfolgt diejenigen, die übereinstimmen.

Rufen Sie `evaluate_audiences()` **nach dem Festlegen oder Aktualisieren aller relevanten Besucherdaten** und **kurz vor** dem Abrufen einer Feature-Variation oder dem Überprüfen eines Feature Flags auf. Dieser Ansatz stellt sicher, dass Kameleoon den Besucher anhand der aktuellsten verfügbaren Daten auswertet, was eine genaue Audience-Zuweisung basierend auf allen Kriterien ermöglicht.

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

```cpp theme={null}
client.evaluate_audiences(visitor_code);
```

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

<Info>
  In den meisten Fällen müssen Sie nur den Basisfehler `KameleoonException` behandeln, wie das Beispiel zeigt. Wenn jedoch verschiedene Fehlertypen eine Reaktion erfordern, behandeln Sie jeden einzeln basierend auf den spezifischen Anforderungen. Für eine höhere Zuverlässigkeit können Sie zusätzlich allgemeine Sprachfehler behandeln, indem Sie `std::exception` einbeziehen.
</Info>

#### get\_datafile()

<Tip>
  Um alle Feature Flags auszuwerten, verwenden Sie [`get_variations()`](#get_variations). Diese Methode ist effizienter als das Aufrufen von `DataFile` und das Iterieren durch Flags mit [`get_variation()`](#get_variation).
</Tip>

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

Das zurückgegebene `DataFile` ist eine Kopie der aktuellen Konfiguration: Es ändert sich nicht, wenn das SDK seine Konfiguration aktualisiert.

```cpp theme={null}
using namespace kameleoon;

DataFile datafile = client.get_datafile();
```

##### Rückgabewert

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

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |

### Besucherdaten

#### get\_visitor\_code()

Verwenden Sie `get_visitor_code()`, um den aktuellen Kameleoon-`visitor_code` des Besuchers zu erhalten. Die Methode funktioniert mit jedem Cookie-Speicher, der das `CookieAccessor`-Interface implementiert.

Die Implementierungslogik ist wie folgt:

1. Das SDK prüft, ob über den bereitgestellten Accessor bereits ein `kameleoonVisitorCode`-Cookie verfügbar ist.
2. Wenn das Cookie nicht vorhanden ist, verwendet das SDK `default_visitor_code`, wenn Sie einen bereitstellen.
3. Andernfalls generiert das SDK einen neuen Besuchercode und speichert ihn über den Accessor.

Weitere Informationen finden Sie unter [Hybrid-Experimentierung](/de/developer-docs/feature-experimentation/get-started/hybrid-experimentation).

<Warning>
  Wenn Sie Ihren eigenen `visitor_code` bereitstellen, muss dessen Eindeutigkeit von Ihrer Seite garantiert werden. Beachten Sie auch, dass die Länge des `visitor_code` auf `255` Zeichen begrenzt ist.
</Warning>

<Info>
  Mit der Methode `get_visitor_code()` können Sie **simulierte** Variationen für einen Besucher festlegen. Wenn Cookies (aus einer **Anfrage** oder einem **Dokument**) den Schlüssel `kameleoonSimulationFFData` enthalten, liest die Methode das Cookie und speichert die simulierten Variationen für diesen Besucher; ihr Rückgabewert ändert sich nicht. Nachfolgende Feature-Auswertungen für den Besucher, wie [`get_variation()`](#get_variation) und [`is_feature_active()`](#is_feature_active), umgehen dann den Standardauswertungsprozess und geben die simulierte [`Variation`](#variation) basierend auf den bereitgestellten Daten zurück.

  Sie können Simulationen auf zwei Arten anwenden:

  * **Automatisch (empfohlen):** Bei Verwendung von Kameleoon Web Experimentation oder dem SDK im [Hybridmodus](/de/developer-docs/feature-experimentation/get-started/hybrid-experimentation#feature-experimente-mit-frontend-tracking-code-verknüpfen) erstellt Kameleoon das Cookie automatisch, wenn Sie die Anzeige einer Variante mithilfe des [Simulationspanels](/de/user-manual/experimentation/feature-experimentation/using-the-rollout-planner/validation-and-rollback/using-simulation-mode) simulieren.
  * **Manuell:** Setzen Sie das Cookie `kameleoonSimulationFFData` manuell.

  Es ist wichtig, **simulierte** Variationen von **[erzwungenen](#set_forced_variation)** Variationen zu unterscheiden:

  * **Simulierte Variationen**: Beeinflussen das Gesamtergebnis des **Feature Flags**.
  * **Erzwungene Variationen**: Sind spezifisch für ein einzelnes Experiment.

  ⚙️ **Manuelle Einrichtung**

  Bitte stellen Sie sicher, dass das Cookie `kameleoonSimulationFFData` diesem Format folgt:

  * `kameleoonSimulationFFData={"featureKey":{"expId":10,"varId":20}}`: Simuliert die Variation mit `varId` des Experiments `expId` für den angegebenen `featureKey`.
  * `kameleoonSimulationFFData={"featureKey":{"expId":0}}`: Simuliert die Standardvariation (definiert im Abschnitt **Then, for everyone else in Production, serve**) für den angegebenen `featureKey`.

  ⚠️ Um eine ordnungsgemäße Funktionalität zu gewährleisten, muss der Cookie-Wert mit einer Methode wie [`encodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) als URI-Komponente codiert werden.
</Info>

##### `CookieAccessor`-Interface

Implementieren Sie `kameleoon::CookieAccessor`, um Cookie-Lese- und -Schreibvorgänge des SDK an Ihr HTTP-Framework anzubinden:

| Methode | Beschreibung |
| - | - |
| `std::optional<std::string> get(const std::string& key)` | Gibt den Cookie-Wert für `key` zurück oder `std::nullopt`, wenn das Cookie nicht vorhanden ist. |
| `void set(const std::string& key, const std::string& value, uint32_t max_age, std::optional<std::string> top_level_domain)` | Speichert das Cookie in der Antwort, mit dem `max_age` (in Sekunden) und, falls vorhanden, der `top_level_domain` als Cookie-Domain. |

<Note>
  * `get()` muss ein bereits über `set()` in die Antwort geschriebenes Cookie bevorzugt gegenüber dem gleichnamigen Request-Cookie zurückgeben. Das SDK behält zwischen den Aufrufen keinen Cookie-Zustand, daher sorgt dies dafür, dass ein zweiter `get_visitor_code()`-Aufruf innerhalb derselben Anfrage den vom ersten Aufruf geschriebenen Code zurückgibt, anstatt einen neuen zu generieren.
  * Die Overrides werden aus dem SDK heraus aufgerufen und dürfen keine Ausnahmen werfen. Eine Ausnahme, die `get()` entkommt, wird als nicht vorhandenes Cookie behandelt. Cookie-Werte müssen gültiges UTF-8 sein.
</Note>

<Tabs>
  <Tab title="Custom">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    #include <optional>
    #include <string>
    #include <unordered_map>

    using namespace kameleoon;

    // A cookie accessor over the cookies of an HTTP request. Cookies written by the
    // SDK are collected in `response_` and must be emitted as `Set-Cookie` headers.
    class RequestCookies final : public CookieAccessor {
    public:
        explicit RequestCookies(std::unordered_map<std::string, std::string> request)
            : request_(std::move(request)) {}

        void set(const std::string& key, const std::string& value, uint32_t max_age,
                 std::optional<std::string> top_level_domain) override {
            response_[key] = value;
            // Emit a `Set-Cookie` header with `max_age` and `top_level_domain` here.
        }

        std::optional<std::string> get(const std::string& key) override {
            // Prefer a cookie already written to the response in this request.
            if (const auto it = response_.find(key); it != response_.end()) return it->second;
            if (const auto it = request_.find(key); it != request_.end()) return it->second;
            return std::nullopt;
        }

    private:
        std::unordered_map<std::string, std::string> request_;
        std::unordered_map<std::string, std::string> response_;
    };

    RequestCookies cookies{parse_request_cookies(request)};

    // Generate or retrieve a visitor code using an auto-generated value
    std::string visitor_code = client.get_visitor_code(cookies);
    // Generate or retrieve a visitor code using a predefined user ID
    std::string visitor_code_with_default = client.get_visitor_code(cookies, "user_id");
    ```
  </Tab>

  <Tab title="Drogon">
    ```cpp theme={null}
    #include "kameleoon/kameleoon.hpp"

    #include <drogon/drogon.h>

    #include <map>
    #include <optional>
    #include <string>

    using namespace kameleoon;

    // Reads cookies from the request Drogon already parsed and collects the
    // SDK's cookies for the response.
    class DrogonCookieAccessor final : public CookieAccessor {
    public:
        explicit DrogonCookieAccessor(const drogon::HttpRequestPtr& request) : request_(request) {}

        void set(const std::string& key, const std::string& value, uint32_t max_age,
                 std::optional<std::string> top_level_domain) override {
            drogon::Cookie cookie{key, value};
            cookie.setPath("/");
            cookie.setMaxAge(static_cast<int>(max_age));
            if (top_level_domain.has_value() && !top_level_domain->empty()) {
                cookie.setDomain(std::move(*top_level_domain));
            }
            // Keyed by name: setting the same cookie twice yields one header.
            response_[key] = std::move(cookie);
        }

        std::optional<std::string> get(const std::string& key) override {
            // Check response cookies first, then fall back to request cookies
            if (const auto it = response_.find(key); it != response_.end()) return it->second.value();
            const auto& request_cookies = request_->getCookies();
            if (const auto it = request_cookies.find(key); it != request_cookies.end()) return it->second;
            return std::nullopt;
        }

        // Attach the SDK cookies to the response
        void apply(const drogon::HttpResponsePtr& response) const {
            for (const auto& [name, cookie] : response_) response->addCookie(cookie);
        }

    private:
        drogon::HttpRequestPtr request_;
        std::map<std::string, drogon::Cookie> response_;
    };

    void get_visitor_code(const drogon::HttpRequestPtr& request,
                          std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
        DrogonCookieAccessor cookies{request};

        // Retrieve or generate a visitor code using the SDK
        std::string visitor_code = client.get_visitor_code(cookies);

        auto response = drogon::HttpResponse::newHttpResponse();
        response->setBody(visitor_code);
        // Attach any new/updated cookies to the response headers
        cookies.apply(response);
        callback(response);
    }
    ```
  </Tab>
</Tabs>

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `cookies` <Badge color="red" size="sm">erforderlich</Badge> | `CookieAccessor&` | Cookie-Accessor zum Lesen und Speichern des Besucher-Cookies. |
| `default_visitor_code` <Badge color="green" size="sm">optional</Badge> | `std::optional<std::string>` | Zu verwendender Besuchercode, wenn kein Cookie vorhanden ist. |

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `std::string` | Zeichenkette, die einen im SDK verwendeten eindeutigen Besuchercode darstellt. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::InvalidSimVarCookieFormat` | Zeigt an, dass das Cookie `kameleoonSimulationFFData` fehlerhaft formatiertes JSON enthält und die simulierten Variationen nicht analysiert werden konnten. |

#### add\_data()

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

Die Methode `add_data()` gibt keinen Wert zurück und interagiert nicht selbstständig mit den Kameleoon-Backend-Servern. Stattdessen speichert das SDK alle deklarierten Daten für die zukünftige Übertragung mit der Methode [`flush()`](#flush). Dieser Ansatz reduziert die Anzahl der Serveraufrufe, da die Daten in der Regel zu einem einzigen Serveraufruf zusammengefasst werden, der durch `flush()` ausgelöst wird.

Die Methode [`track_conversion()`](#track_conversion) sendet ebenfalls alle zuvor verknüpften Daten, genau wie `flush()`. Dasselbe gilt für die Methoden [`get_variation()`](#get_variation) und [`get_variations()`](#get_variations), wenn eine Experimentierungsregel ausgelöst wird.

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

Der Parameter `data` ist ein `std::vector<Data>`, wobei `Data` ein `std::variant` aller [Datentypen](#datentypen) ist. Jeder Datentyp wird implizit in `Data` konvertiert, sodass Sie eine geschweifte Liste von Datenobjekten übergeben können.

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {Browser{.type = BrowserType::Chrome, .version = 123.0F}});

client.add_data(visitor_code, {
    PageView{.url = "https://example.com/pricing", .title = "Pricing", .referrers = {3}},
    UserAgent{"Mozilla/5.0"},
});

// Stores the data locally for targeting only, without sending it to Kameleoon
client.add_data(visitor_code, {PageView{.url = "https://example.com/checkout", .title = "Checkout"}}, false);
```

##### Parameter

| Name | Typ | Beschreibung | Standardwert |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. | |
| `data` <Badge color="red" size="sm">erforderlich</Badge> | `const std::vector<Data>&` | Sammlung von Kameleoon-Datentypen. | |
| `track` <Badge color="green" size="sm">optional</Badge> | `bool` | Gibt an, ob die hinzugefügten Daten für das Tracking geeignet sind. Wenn auf `false` gesetzt, speichert das SDK die Daten lokal, verwendet sie nur für die Targeting-Auswertung und sendet sie nicht an die Kameleoon Data API. | `true` |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::InvalidArgument` | Eine Zeichenkette ist kein gültiges UTF-8 oder ein Enum-Wert ist unbekannt. |

#### flush()

* *📨 Sendet Tracking-Daten an Kameleoon*

Die Methode `flush()` aggregiert alle einem Besucher zugeordneten Kameleoon-Daten und sendet eine Tracking-Anfrage an den Server. Diese Anfrage umfasst alle zuvor über die Methode [`add_data`](#add_data) hinzugefügten Daten, die noch nicht über andere Tracking-Mechanismen übertragen wurden (siehe die referenzierten Methoden für Details). Die `flush()`-Operation ist nicht blockierend, da der Serveraufruf asynchron erfolgt.

Diese Methode bietet Kontrolle darüber, wann die mit einem bestimmten `visitor_code` verknüpften Daten übertragen werden. Wenn `add_data()` beispielsweise mehrmals aufgerufen wird, wäre das Senden einer Anfrage nach jedem Aufruf ineffizient. Stattdessen können Sie diese Aktualisierungen bündeln und `flush()` einmal aufrufen, um alle gesammelten Daten in einer einzigen Anfrage zu senden.

Die Methode `flush()` verwendet den bereitgestellten `visitor_code` als eindeutige Besucherkennung.

<Tip>
  * `flush()`: Stellt eine Flush-Operation gemäß dem konfigurierten Tracking-Intervall in die Warteschlange.
  * `flush_instant()`: Sendet Tracking-Daten sofort, ohne auf das Intervall zu warten.
</Tip>

```cpp theme={null}
// Queues a flush operation for the given visitor_code.
// Data will be sent according to the configured tracking interval (non-blocking).
client.flush(visitor_code);

// Immediately sends all pending tracking data for the given visitor_code
// and blocks until the request completes.
client.flush_instant(visitor_code);

// Immediately sends all pending tracking data without blocking.
client.flush_instant_async(visitor_code, [](std::exception_ptr error) {
    // The immediate tracking operation completed.
});

// C++20 coroutines
co_await client.co_flush_instant(visitor_code);
```

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

#### get\_remote\_data()

Mit der Methode `get_remote_data()` können Sie Remote-Daten abrufen, die auf Kameleoon-Servern für den angegebenen `key` gespeichert sind. In den meisten Setups werden diese Daten über die Kameleoon Data API geschrieben und können später von Ihrem C++-Dienst abgerufen werden, wann immer Sie zusätzlichen Anwendungskontext benötigen.

Diese Methode ist nützlich, wenn Sie strukturierte Informationen auf der Remote-Infrastruktur von Kameleoon aufbewahren und von Ihrem Backend aus wiederverwenden möchten, ohne einen separaten Abrufmechanismus zu pflegen.

```cpp theme={null}
// Blocking
std::string data = client.get_remote_data("test-key");

// Completion: the value is only meaningful when `error` is null
client.get_remote_data_async("test-key", [](std::exception_ptr error, std::string data) {
    if (!error) {
        // Use `data`.
    }
});

// C++20 coroutines
std::string data = co_await client.co_get_remote_data("test-key");
```

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `key` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Schlüssel, der den Remote-Daten zugeordnet ist, die Sie abrufen möchten. |

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `std::string` | Nutzlast, die dem angegebenen `key` zugeordnet ist. In den meisten Fällen ist die Nutzlast als Zeichenkette serialisiertes JSON. Die Nutzlast ist eine Byte-Zeichenkette und kann beliebige Bytes enthalten. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::Network` | Wird ausgelöst, wenn die Remote-Daten-Anfrage fehlschlägt oder der Server mit einem nicht erfolgreichen Statuscode antwortet. |

#### get\_remote\_visitor\_data()

`get_remote_visitor_data()` ruft Kameleoon-Besuchsdaten für den angegebenen `visitor_code` ab. Die Methode fügt die Daten dem lokalen Besucherspeicher hinzu, damit andere SDK-Methoden sie für Targeting-Entscheidungen verwenden können.

Mit dieser Methode erhaltene Daten sind besonders nützlich, wenn Sie:

* von anderen Geräten gesammelte Daten verwenden möchten.
* auf den Verlauf eines Besuchers zugreifen möchten, z. B. zuvor angesehene Seiten aus vergangenen Besuchen.
* Daten verwenden möchten, die nur auf der Clientseite verfügbar sind, wie z. B. Datalayer-Variablen und Frontend-Ziel-Conversions.

Lesen Sie [diesen Artikel](/de/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation), um die möglichen Anwendungsfälle besser zu verstehen.

<Warning>
  Standardmäßig ruft `get_remote_visitor_data()` automatisch die zuletzt gespeicherten Custom Data mit `scope=Visitor` ab und fügt sie dem Besucher hinzu, ohne dass [`add_data()`](#add_data) aufgerufen werden muss. Dies ist besonders nützlich für die [Synchronisierung von Custom Data über mehrere Geräte hinweg](/de/developer-docs/cross-device-experimentation).
</Warning>

```cpp theme={null}
using namespace kameleoon;

// Fetch remote visitor data without any filter
// This will return all available data for the given visitor
client.get_remote_visitor_data(visitor_code);

// Create a filter to limit the returned data
RemoteVisitorDataFilter filter{
    .previous_visit_amount = 5,  // Include data from the last 5 visits
    .page_views = true,          // Include page view history
    .conversions = true,         // Include conversion events (e.g., goals, transactions)
};

// Fetch remote visitor data using the specified filter
// This will return only the data matching the filter criteria
client.get_remote_visitor_data(visitor_code, filter);

// Non-blocking form
client.get_remote_visitor_data_async(visitor_code, filter, [](std::exception_ptr error) {
    // The data is available locally when `error` is null.
});

// C++20 coroutines
co_await client.co_get_remote_visitor_data(visitor_code, filter);
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Besuchercode, dessen Daten abgerufen werden sollen. | |
| `filter` <Badge color="green" size="sm">optional</Badge> | `RemoteVisitorDataFilter` | Filter, der beschreibt, welche Remote-Besucherdaten abgerufen werden sollen. | `RemoteVisitorDataFilter{}` |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::Network` | Wird ausgelöst, wenn die Anfrage für Remote-Besucherdaten fehlschlägt, nicht analysiert werden kann oder der Server mit einem nicht erfolgreichen Statuscode antwortet. |

##### Verwendung von Parametern in get\_remote\_visitor\_data()

Mit der Methode `get_remote_visitor_data()` können Sie steuern, welche Daten für einen Besucher abgerufen werden. Derselbe Filteransatz funktioniert für Ziele, Experimente, Variationen und andere Besucherdaten.

Wenn Sie beispielsweise Benutzer ansprechen möchten, die bei ihren letzten fünf Besuchen für ein Ziel konvertiert haben, können Sie `previous_visit_amount` auf `5` und `conversions` auf `true` setzen.

Die in diesem Beispiel gezeigte Flexibilität ist nicht auf Zieldaten beschränkt. Sie können den Filter verwenden, um viele verschiedene Besucherverhalten abzurufen und sie der Targeting- und Reporting-Logik in Ihrer C++-Anwendung zur Verfügung zu stellen.

##### `RemoteVisitorDataFilter`-Felder

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `previous_visit_amount` | `uint32_t` | Anzahl der vorherigen Besuche, aus denen Daten abgerufen werden sollen. | `1` |
| `current_visit` | `bool` | Wenn `true`, werden die Daten des aktuellen Besuchs abgerufen. | `true` |
| `custom_data` | `bool` | Wenn `true`, werden Custom Data abgerufen. | `true` |
| `visitor_code` | `bool` | Wenn `true`, wird der zuletzt verwendete Besuchercode wiederverwendet. | `true` |
| `page_views` | `bool` | Wenn `true`, werden Seitenaufrufdaten abgerufen. | `false` |
| `geolocation` | `bool` | Wenn `true`, werden Geolokalisierungsdaten abgerufen. | `false` |
| `device` | `bool` | Wenn `true`, werden Gerätedaten abgerufen. | `false` |
| `browser` | `bool` | Wenn `true`, werden Browserdaten abgerufen. | `false` |
| `operating_system` | `bool` | Wenn `true`, werden Betriebssystemdaten abgerufen. | `false` |
| `conversions` | `bool` | Wenn `true`, werden Conversion-Daten abgerufen. | `false` |
| `experiments` | `bool` | Wenn `true`, werden Experiment-Daten abgerufen. | `false` |
| `kcs` | `bool` | Wenn `true`, werden Kameleoon Conversion Score-Daten abgerufen. | `false` |
| `personalizations` | `bool` | Wenn `true`, werden Personalisierungsdaten abgerufen. | `false` |
| `cbs` | `bool` | Wenn true, ruft das SDK Contextual Bandit Score-Daten ab. | `false` |

#### get\_visitor\_warehouse\_audience()

Diese Methode ruft Audience-Daten ab, die einem Besucher in Ihrer Warehouse-Integration zugeordnet sind, indem sie den angegebenen `visitor_code` und optional einen `warehouse_key` verwendet. Der `warehouse_key` ist normalerweise Ihre interne Benutzer-ID. Der Parameter `custom_data_index` entspricht den Kameleoon-Custom-Data, die Kameleoon verwendet, um Ihre Besucher anzusprechen.

Wenn der Aufruf erfolgreich ist, konvertiert das SDK die zurückgegebene Audience-Liste in [`CustomData`](#customdata), fügt sie dem Besucher lokal hinzu und macht sie für Targeting-Zwecke verfügbar. Weitere Hintergrundinformationen finden Sie in der [Warehouse-Targeting-Dokumentation](/de/user-manual/integrations/data-warehouses/bigquery/use-bigquery-as-a-source-audience-targeting).

```cpp theme={null}
// Fetch audience data for a visitor using only the visitor_code.
client.get_visitor_warehouse_audience(visitor_code, 98);

// Fetch audience data for a visitor using both visitor_code and warehouse_key.
// Useful when your warehouse uses a different identifier than visitor_code.
client.get_visitor_warehouse_audience(visitor_code, 98, "internal-user-id");

// Non-blocking form
client.get_visitor_warehouse_audience_async(visitor_code, 98, "internal-user-id", [](std::exception_ptr error) {
    // The audience data is available locally when `error` is null.
});

// C++20 coroutines
co_await client.co_get_visitor_warehouse_audience(visitor_code, 98, "internal-user-id");
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Besucher, dessen Warehouse-Audiences abgerufen werden sollen. | |
| `custom_data_index` <Badge color="red" size="sm">erforderlich</Badge> | `uint32_t` | In Kameleoon konfigurierter Custom-Data-Index für das Warehouse-Audience-Targeting. | |
| `warehouse_key` <Badge color="green" size="sm">optional</Badge> | `std::optional<std::string>` | Externer Warehouse-Schlüssel, normalerweise Ihre interne Benutzer-ID. Wird er weggelassen, verwendet das SDK den `visitor_code`. | `std::nullopt` |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |
| `ErrorCode::Network` | Wird ausgelöst, wenn die Warehouse-Audience-Anfrage fehlschlägt, nicht analysiert werden kann oder der Server mit einem nicht erfolgreichen Statuscode antwortet. |

#### set\_legal\_consent()

Sie müssen diese Methode verwenden, um anzugeben, ob der Besucher seine rechtliche Einwilligung zur Verwendung personenbezogener Daten gegeben hat. Das Setzen von `consent` auf `false` schränkt die Datentypen ein, die in Tracking-Anfragen aufgenommen werden können. Dies hilft Ihnen, rechtliche und regulatorische Anforderungen einzuhalten und gleichzeitig Besucherdaten verantwortungsbewusst zu verwalten. Weitere Informationen finden Sie in der [Richtlinie zur Einwilligungsverwaltung](/de/user-manual/project-management/consent-management-policy).

Wenn Sie einen `CookieAccessor` übergeben, aktualisiert das SDK auch die Besucher-Cookies entsprechend dem Einwilligungsstatus.

```cpp theme={null}
// Set consent and update cookies
client.set_legal_consent(visitor_code, true, &cookies);

// Set consent without updating cookies
client.set_legal_consent(visitor_code, true);
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Die eindeutige Kennung des Benutzers. | |
| `consent` <Badge color="red" size="sm">erforderlich</Badge> | `bool` | `true` gibt an, dass der Besucher seine rechtliche Einwilligung gegeben hat, `false` gibt an, dass der Besucher nie eine rechtliche Einwilligung erteilt oder diese zurückgezogen hat. | |
| `cookies` <Badge color="green" size="sm">optional</Badge> | `CookieAccessor*` | Optionaler Cookie-Accessor zur Aktualisierung von Cookies. | `nullptr` |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

##### Verhalten beim Widerruf der Einwilligung

Wenn Sie `set_legal_consent()` mit `consent=false` aufrufen, löscht das SDK das `kameleoonVisitorCode`-Cookie nicht. Stattdessen verlängert es das Ablaufdatum des Cookies nicht mehr, sodass das Cookie bis zu seinem natürlichen Ablauf bestehen bleibt.

Wenn Ihre Compliance-Anforderungen die sofortige Entfernung der Cookie-Datei beim Opt-out vorschreiben, müssen Sie sie manuell mit den nativen Cookie-Verwaltungsmethoden Ihres Frameworks löschen. Das SDK entfernt die Datei nicht automatisch.

### Ziele und Drittanbieter-Analytik

#### track\_conversion()

* 📨 *Sendet Tracking-Daten an Kameleoon*

Verwenden Sie diese Methode, um eine Conversion für ein bestimmtes [Ziel](/de/user-manual/assets/goals/create-a-goal) und einen bestimmten Benutzer zu verfolgen. Diese Methode erfordert `visitor_code` und `goal_id`. Darüber hinaus akzeptiert diese Methode auch die optionalen Argumente `revenue`, `negative` und `metadata`. Der `visitor_code` ist in der Regel identisch mit dem, der beim Auslösen des Experiments verwendet wurde.

<Tip>
  Diese Methode ist nicht blockierend, da das SDK den Serveraufruf asynchron durchführt.
</Tip>

```cpp theme={null}
using namespace kameleoon;

// Track a goal
client.track_conversion(visitor_code, goal_id);

// Track a goal with revenue
client.track_conversion(visitor_code, goal_id, TrackConversionOptions{.revenue = 100.0F});

// Track a goal with negative revenue
client.track_conversion(
    visitor_code, goal_id, TrackConversionOptions{.revenue = 100.0F, .negative = true});

// Track a goal with custom metadata
client.track_conversion(
    visitor_code, goal_id, TrackConversionOptions{.metadata = {CustomData(4, {"true"})}});
```

##### Parameter

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. | |
| `goal_id` <Badge color="red" size="sm">erforderlich</Badge> | `uint32_t` | ID des Ziels. | |
| `revenue` <Badge color="green" size="sm">optional</Badge> | `float` | Umsatz der Conversion. | `0` |
| `negative` <Badge color="green" size="sm">optional</Badge> | `bool` | Definiert, ob der Umsatz positiv oder negativ ist. | `false` |
| `metadata` <Badge color="green" size="sm">optional</Badge> | `std::vector<CustomData>` | Metadaten der Conversion. [Müssen zuvor in der Kameleoon-App definiert werden](/de/user-manual/assets/goals/create-a-goal#metadata). | `{}` |

<Note>
  Die optionalen Parameter `revenue`, `negative` und `metadata` werden als Felder einer `TrackConversionOptions`-Struktur übergeben.
</Note>

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

  Wenn Sie den Parameter `metadata` angeben, verwendet Kameleoon diese angegebenen Werte für die aktuelle Conversion anstelle dessen, was Sie zuvor mit der Methode [`add_data()`](#add_data) gesammelt haben. Wenn Sie den Parameter weglassen, verwendet Kameleoon die zuletzt verfolgten Werte für diese [`CustomData`](#customdata) vor der Conversion und innerhalb desselben Besuchs.

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

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

  ```cpp theme={null}
  client.add_data(visitor_code, {
      CustomData(5, {"Credit Card"}),
      CustomData(9, {"Express Delivery"}),
  });

  client.track_conversion(
      visitor_code, goal_id, TrackConversionOptions{.metadata = {CustomData(5, {"Amex Credit Card"})}});
  ```
</Note>

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

#### get\_engine\_tracking\_code()

Kameleoon lässt sich in mehrere Analyselösungen integrieren, darunter Mixpanel, Google Analytics 4 und Segment. Um serverseitige Experimente korrekt zu verfolgen, rufen Sie die Methode `get_engine_tracking_code()` auf, nachdem der Besucher ein Experiment ausgelöst hat. Das SDK gibt JavaScript-Warteschlangenbefehle für die Experimente zurück, die der Besucher in den letzten fünf Sekunden ausgelöst hat. Wenn Sie diesen Code in die Seite einfügen, verarbeitet Engine.js die Befehle und sendet die Expositions-Events über die aktive Analyseintegration.

Weitere Informationen zur Implementierung dieser Methode finden Sie unter [Hybrid-Experimentierung](/de/developer-docs/feature-experimentation/get-started/hybrid-experimentation).

```cpp theme={null}
std::string tracking_code = client.get_engine_tracking_code(visitor_code);
```

<Note>
  * Um diese Funktion zu nutzen, implementieren Sie sowohl das C++ SDK als auch [Engine.js](/de/developer-docs/web-experimentation/implementation-and-deployment/standard-implementation) von Kameleoon. Da Engine.js in diesem Flow nur für das Tracking verwendet wird, können Sie das asynchrone Tag vor dem schließenden `</body>`-Tag installieren.
  * Wenn Sie Experimente nur in Kameleoon verfolgen möchten und keine Expositions-Events an Drittanbieter-Analysetools senden müssen, verwenden Sie das [JavaScript / TypeScript SDK](/de/developer-docs/sdks/web-sdks/js-sdk). Diese Option eignet sich gut für [Serverless-Edge-Compute-Plattformen](/de/developer-docs/feature-experimentation/implementation-and-deployment/serverless-edge-compute-starter-kits). Das JavaScript / TypeScript SDK verfolgt Variationen automatisch, wenn Sie [`getVisitorCode`](/de/developer-docs/sdks/web-sdks/js-sdk#getvisitorcode) aufrufen, solange Sie die entsprechenden Experimentzuweisungen zu `window.kameleoonQueue` hinzufügen.
  * Sie können den zurückgegebenen Tracking-Code direkt in ein HTML-`<script>`-Tag einfügen.

  ```html theme={null}
  <html lang="en">
    <body>
      <script>
        const engineTrackingCode = `
          window.kameleoonQueue = window.kameleoonQueue || [];
          window.kameleoonQueue.push(['Experiments.assignVariation', 123456, 7890, true]);
          window.kameleoonQueue.push(['Experiments.trigger', 123456, true]);
          window.kameleoonQueue.push(['Experiments.assignVariation', 234567, 8901, true]);
          window.kameleoonQueue.push(['Experiments.trigger', 234567, true]);
        `;
        const script = document.createElement('script');

        script.textContent = engineTrackingCode;
        document.body.appendChild(script);
      </script>

    </body>
  </html>
  ```

  In diesem Beispiel sind `123456` und `234567` Experiment-IDs und `7890` und `8901` Variations-IDs. In Ihrer Implementierung generiert das SDK diese Werte im zurückgegebenen Tracking-Code.
</Note>

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `visitor_code` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Eindeutige Kennung des Besuchers. |

##### Rückgabewert

| Typ | Beschreibung |
| - | - |
| `std::string` | JavaScript-Code zum Einfügen in die Seite. |

##### Fehler

| Typ | Beschreibung |
| - | - |
| `ErrorCode::Initialization` | Gibt an, dass das SDK noch nicht vollständig initialisiert ist. |
| `ErrorCode::VisitorCodeInvalid` | Ausnahme, die angibt, dass der angegebene Besuchercode ungültig ist. Er ist entweder leer oder länger als 255 Zeichen. |

### Ereignisse

#### set\_event\_handler()

Verwenden Sie diese Methode, um einen Handler für SDK-Ereignisse zu registrieren. Das SDK ruft den Handler auf, wenn das ausgewählte Ereignis eintritt. Der Client behält höchstens einen Handler pro Ereignistyp: Die Registrierung eines neuen Handlers für denselben Ereignistyp ersetzt den vorherigen Handler.

Der verwendete `EventHandler`-Konstruktor (`EventHandler::datafile_update()` oder `EventHandler::http_request()`) wählt den Ereignistyp aus, sodass ein Handler und die Ereignisse, die er empfängt, nicht aus dem Takt geraten können. Die Übergabe einer leeren `std::function` (`{}`) entfernt den aktuellen Handler für den ausgewählten Ereignistyp.

<Tabs>
  <Tab title="datafile_update">
    ```cpp theme={null}
    #include "kameleoon/events.hpp"

    using namespace kameleoon;

    client.set_event_handler(EventHandler::datafile_update([](const DataFileUpdateEvent& event) {
        DataFileUpdateSource source = event.source; // DataFileUpdateSource::Polling or DataFileUpdateSource::Streaming
        uint64_t date_modified = event.date_modified; // Data file modification date in milliseconds.

        // React to the data file update.
    }));

    // Clear the handler.
    client.set_event_handler(EventHandler::datafile_update({}));
    ```

    <Tip>
      `DataFileUpdateEvent` enthält Informationen über eine Aktualisierung der SDK-Datendatei.

      | Name | Typ | Beschreibung |
      | - | - | - |
      | `source` | `DataFileUpdateSource` | Die Aktualisierungsquelle. [`DataFileUpdateSource::Polling`](/de/developer-docs/feature-experimentation/technical-reference/technical-considerations#polling-standard) gibt eine geplante Datendatei-Aktualisierung an, und [`DataFileUpdateSource::Streaming`](/de/developer-docs/feature-experimentation/technical-reference/technical-considerations#streaming-premium-option) gibt eine Echtzeit-Aktualisierung an, die im Streaming-Modus empfangen wurde. |
      | `date_modified` | `uint64_t` | Das Änderungsdatum der aktualisierten Datendatei in Millisekunden. |
    </Tip>
  </Tab>

  <Tab title="http_request">
    ```cpp theme={null}
    #include "kameleoon/events.hpp"

    #include <variant>

    using namespace kameleoon;

    client.set_event_handler(EventHandler::http_request([](const HttpRequestEvent& event) {
        if (const auto* succeeded = std::get_if<HttpRequestSucceeded>(&event)) {
            // The SDK request completed successfully.
            RequestType request_type = succeeded->request_type;
            uint16_t http_status = succeeded->http_status;
            std::chrono::milliseconds duration = succeeded->duration;
        } else if (const auto* failed = std::get_if<HttpRequestFailed>(&event)) {
            // The SDK request failed.
            HttpRequestFailureReason reason = failed->failure.reason; // HttpStatus, Error, or Cancelled
            std::optional<uint16_t> http_status = failed->failure.http_status;
            std::optional<std::string> cause = failed->failure.cause;
        }
    }));

    // Clear the handler.
    client.set_event_handler(EventHandler::http_request({}));
    ```

    <Tip>
      `HttpRequestEvent` ist ein `std::variant<HttpRequestSucceeded, HttpRequestFailed>`. Das SDK meldet das Ereignis einmal pro tatsächlichem HTTP-Anfrageversuch, einschließlich Wiederholungen. Verwenden Sie `std::get_if` oder `std::visit`, um eine erfolgreiche Anfrage von einer fehlgeschlagenen zu unterscheiden.

      | Typ | Beschreibung |
      | - | - |
      | `HttpRequestSucceeded` | Beschreibt eine SDK-HTTP-Anfrage, die erfolgreich abgeschlossen wurde. Enthält immer `http_status`. |
      | `HttpRequestFailed` | Beschreibt eine SDK-HTTP-Anfrage, die aufgrund eines HTTP-Status, eines Fehlers oder eines Abbruchs fehlgeschlagen ist. Enthält immer `failure`. |

      <Accordion title="Ereignisdatenfelder und Fehlerdetails">
        ##### Ereignisdatenfelder

        | Name | Typ | Beschreibung |
        | - | - | - |
        | `request_type` | `RequestType` | Der SDK-Anfragetyp. Mögliche Werte sind `RequestType::DataFile`, `RequestType::Tracking`, `RequestType::RemoteVisitorData`, `RequestType::RemoteData` und `RequestType::AccessToken`. |
        | `http_status` | `uint16_t` | Der von der Anfrage zurückgegebene HTTP-Statuscode. Nur in `HttpRequestSucceeded` vorhanden. |
        | `failure` | `HttpRequestFailure` | Details darüber, warum die Anfrage fehlgeschlagen ist. Nur in `HttpRequestFailed` vorhanden. |
        | `duration` | `std::chrono::milliseconds` | Die Anfragedauer. |

        ##### HttpRequestFailure

        `HttpRequestFailure` enthält Details über eine fehlgeschlagene SDK-HTTP-Anfrage.

        | Name | Typ | Beschreibung |
        | - | - | - |
        | `reason` | `HttpRequestFailureReason` | Der Fehlergrund. Mögliche Werte sind `HttpRequestFailureReason::HttpStatus`, `HttpRequestFailureReason::Error` und `HttpRequestFailureReason::Cancelled`. |
        | `http_status` | `std::optional<uint16_t>` | Der HTTP-Statuscode für Fehler, die durch eine nicht erfolgreiche HTTP-Antwort verursacht wurden. Dieser Wert ist `std::nullopt` bei Fehlern durch Ausnahmen oder Abbrüche. |
        | `cause` | `std::optional<std::string>` | Die Ausnahme (Fehler), die zum Fehlschlagen der Anfrage geführt hat. Dieser Wert ist `std::nullopt`, wenn die Anfrage aufgrund eines HTTP-Status oder eines Abbruchs fehlgeschlagen ist. |
      </Accordion>
    </Tip>
  </Tab>
</Tabs>

<Note>
  Handler werden synchron auf dem einzelnen Worker-Thread des SDK aufgerufen, daher dürfen sie nicht blockieren: Die in einem Handler verbrachte Zeit verzögert das Datendatei-Polling und das Senden von Tracking-Daten. Sie müssen thread-sicher sein und dürfen keine Ausnahmen werfen: Eine Ausnahme, die einem Handler entkommt, wird abgefangen und verworfen und beeinflusst das SDK-Verhalten nie. Rufen Sie keine blockierenden SDK-Operationen aus einem Handler auf; verwenden Sie stattdessen die `*_async`-Formen und schließen Sie die Arbeit auf einem Anwendungs-Thread ab.

  Ein bereits laufender Aufruf kann abgeschlossen werden, nachdem Sie den Handler entfernt oder den Client zerstört haben, und der Handler (mit seinen Captures) wird auf einem SDK-Thread zerstört, sobald er nicht mehr verwendet wird. Halten Sie erfasste Objekte entsprechend am Leben und thread-sicher. Ein Handler kann sich selbst entfernen oder ersetzen.

  Alle `KameleoonClient`-Instanzen, die für denselben Site-Code und dieselbe Umgebung erstellt wurden, teilen sich einen Handler pro Ereignistyp: Der zuletzt gesetzte Handler gewinnt, und das Zerstören einer dieser Instanzen entfernt ihn. Behalten Sie eine einzige Client-Instanz pro Site-Code und Umgebung.
</Note>

##### Parameter

| Name | Typ | Beschreibung |
| - | - | - |
| `handler` <Badge color="red" size="sm">erforderlich</Badge> | `EventHandler` | Der zu registrierende Handler, erstellt mit `EventHandler::datafile_update()` aus einem `DataFileUpdateHandler` (`std::function<void(const DataFileUpdateEvent&)>`) oder mit `EventHandler::http_request()` aus einem `HttpRequestHandler` (`std::function<void(const HttpRequestEvent&)>`). Übergeben Sie eine leere `std::function`, um den aktuellen Handler für diesen Ereignistyp zu entfernen. |

### Datentypen

Dieser Abschnitt listet die vom SDK im Namespace `kameleoon` deklarierten C++-Datentypen auf (`kameleoon/data/*.hpp`). Alle davon sind einfache Strukturen, die Sie an [`add_data()`](#add_data) übergeben.

#### ApplicationVersion

`ApplicationVersion` stellt die semantische Versionsnummer Ihrer Anwendung dar.

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

| Name | Typ | Beschreibung |
| - | - | - |
| `value` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Die Anwendungsversion. Dieses Feld muss der semantischen Versionierung folgen. Akzeptierte Formate sind `major`, `major.minor` oder `major.minor.patch`. |

```cpp theme={null}
using namespace kameleoon;

// major
client.add_data(visitor_code, {ApplicationVersion{"10"}});
// major.minor
client.add_data(visitor_code, {ApplicationVersion{"10.20"}});
// major.minor.patch
client.add_data(visitor_code, {ApplicationVersion{"10.20.30"}});
```

#### Browser

Der hier gespeicherte `Browser`-Datensatz kann verwendet werden, um Experiment- und Personalisierungsberichte nach jedem damit verknüpften Wert zu filtern.

| Name | Typ | Beschreibung |
| - | - | - |
| `type` <Badge color="red" size="sm">erforderlich</Badge> | `BrowserType` | Liste der Browser: `BrowserType::Chrome`, `BrowserType::InternetExplorer`, `BrowserType::Firefox`, `BrowserType::Safari`, `BrowserType::Opera`, `BrowserType::Other`. |
| `version` <Badge color="green" size="sm">optional</Badge> | `std::optional<float>` | Version des Browsers, die Gleitkommazahl stellt die Haupt- und Nebenversion des Browsers dar |

```cpp theme={null}
using namespace kameleoon;

// Browser data with a version
client.add_data(visitor_code, {Browser{.type = BrowserType::Safari, .version = 26.4F}});
// Browser data without a version
client.add_data(visitor_code, {Browser{.type = BrowserType::Chrome}});
```

#### Conversion

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

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

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `goal_id` <Badge color="red" size="sm">erforderlich</Badge> | `uint32_t` | ID des Ziels. | |
| `revenue` <Badge color="green" size="sm">optional</Badge> | `float` | Umsatz der Conversion | `0` |
| `negative` <Badge color="green" size="sm">optional</Badge> | `bool` | Definiert, ob der Umsatz positiv oder negativ ist. | `false` |
| `metadata` <Badge color="green" size="sm">optional</Badge> | `std::vector<CustomData>` | Metadaten der Conversion. | `{}` |

```cpp theme={null}
using namespace kameleoon;

// Add a simple conversion with ID 32
client.add_data(visitor_code, {Conversion{.goal_id = 32}});

// Add conversion with ID 33 including revenue and marked as negative
client.add_data(visitor_code, {Conversion{.goal_id = 33, .revenue = 10.0F, .negative = true}});

// Add conversion with ID 34 including revenue, negative flag, and custom metadata
client.add_data(visitor_code, {
    Conversion{
        .goal_id = 34,
        .revenue = 10.0F,
        .negative = true,
        .metadata = {
            CustomData(3, {"metadata1", "md2"}),
            CustomData(5, {"md3"}),
        },
    },
});
```

#### Cookie

`Cookie` enthält Informationen über die auf dem Gerät des Besuchers gespeicherten Cookies.

| Name | Typ | Beschreibung |
| - | - | - |
| `cookies` | `std::unordered_map<std::string, std::string>` | Eine Zeichenketten-Map mit Cookie-Schlüsseln und -Werten. |

<Tip>
  Jeder Besucher kann nur einen `Cookie` haben. Das Hinzufügen eines zweiten `Cookie` überschreibt den ersten.
</Tip>

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {Cookie{.cookies = {{"segment", "vip"}}}});
```

#### CustomData

`CustomData` ermöglicht die Zuordnung beliebiger Datentypen zu jedem Besucher und ist somit ein effektives Werkzeug für Targeting-Bedingungen in [Segmenten](/de/user-manual/assets/segments/create-a-segment). Darüber hinaus kann es als Filter oder Aufschlüsselung in Experimentberichten verwendet werden. Weitere Informationen zu Custom Data finden Sie in diesem [Artikel](/de/developer-docs/custom-data).

Definieren Sie Custom-Data-Typen in der Kameleoon-App oder in der Data API und verwenden Sie sie aus dem SDK.

`CustomData` hat zwei Konstruktoren: Einer identifiziert die Custom Data über ihre `id` (Index), der andere über ihren `name`.

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `id`/`name` <Badge color="red" size="sm">erforderlich</Badge> | `uint32_t`/`std::string` | Index oder Name der Custom Data. **Entweder `id` oder `name` muss angegeben werden**, um die Daten zu identifizieren. | |
| `values` <Badge color="red" size="sm">erforderlich</Badge> | `std::vector<std::string>` | Zu speichernde Werte der Custom Data. | |
| `overwrite` <Badge color="green" size="sm">optional</Badge> | `bool` | Flag zur expliziten Steuerung, wie die Werte gespeichert werden und wie sie in Berichten erscheinen. [Mehr anzeigen](/de/developer-docs/custom-data#standardlogik-wenn-der-overwrite-parameter-false-oder-weggelassen-ist) | `true` |

<Note>
  * Jeder Besucher darf nur ein `CustomData` für jede eindeutige `id` (`name`) haben. Das Hinzufügen eines weiteren `CustomData` mit derselben `id` (`name`) ersetzt das vorhandene.

  * Den „Index" der Custom Data finden Sie im [Custom Data-Dashboard](/de/user-manual/assets/custom-data/manage-custom-data) unter der Spalte „INDEX".

  * Um zu verhindern, dass das SDK Daten mit dem ausgewählten Index aus Datenschutzgründen an die Kameleoon-Server sendet, aktivieren Sie die Option: **Use this data only locally for targeting purposes** beim Erstellen von Custom Data.

  * Das Hinzufügen einer mit einem Namen erstellten `CustomData`-Instanz, wenn die SDK-Instanz nicht initialisiert oder der Name nicht registriert ist, führt dazu, dass die Daten ignoriert werden.
</Note>

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {CustomData(1, {"value"})});

// With several values
client.add_data(visitor_code, {CustomData(1, {"value1", "value2"})});

// To set the `overwrite` flag to false
client.add_data(visitor_code, {CustomData(1, {"value"}, false)});

// To use a name instead of the index
client.add_data(visitor_code, {CustomData("my-custom-data", {"value"})});

// To use a name instead of the index and set the `overwrite` flag to false
client.add_data(visitor_code, {CustomData("my-custom-data", {"value"}, false)});
```

#### Device

Sie können Gerätedaten verwenden, um Experiment- und Personalisierungsberichte nach jedem zugeordneten Wert zu filtern.

| Name | Typ | Beschreibung |
| - | - | - |
| `type` | `DeviceType` | Gerätetyp. Mögliche Werte sind `DeviceType::Phone`, `DeviceType::Tablet` und `DeviceType::Desktop`. |

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {Device{DeviceType::Desktop}});
```

#### Geolocation

`Geolocation` enthält die Geolokalisierungsdetails des Besuchers.

| Name | Typ | Beschreibung |
| - | - | - |
| `country` <Badge color="red" size="sm">erforderlich</Badge> | `std::string` | Das Land des Besuchers. |
| `region` <Badge color="green" size="sm">optional</Badge> | <nobr>`std::optional<std::string>`</nobr> | Die Region des Besuchers. |
| `city` <Badge color="green" size="sm">optional</Badge> | <nobr>`std::optional<std::string>`</nobr> | Die Stadt des Besuchers. |
| `postal_code` <Badge color="green" size="sm">optional</Badge> | <nobr>`std::optional<std::string>`</nobr> | Die Postleitzahl des Besuchers. |
| `latitude` <Badge color="green" size="sm">optional</Badge> | `std::optional<float>` | Die Breitengradkoordinate, die den Standort des Besuchers darstellt. Die Koordinatenzahl stellt Dezimalgrade dar. |
| `longitude` <Badge color="green" size="sm">optional</Badge> | `std::optional<float>` | Die Längengradkoordinate, 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>

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {
    Geolocation{
        .country = "France",
        .region = "Ile-de-France",
        .city = "Paris",
        .postal_code = "75009",
        .latitude = 48.8720171F,
        .longitude = 2.3338352F,
    },
});
```

#### OperatingSystem

`OperatingSystem` enthält Informationen über das Betriebssystem auf dem Gerät des Besuchers.

| Name | Typ | Beschreibung |
| - | - | - |
| `type` | `OperatingSystemType` | Betriebssystemfamilie. Mögliche Werte sind `OperatingSystemType::Windows`, `OperatingSystemType::Mac`, `OperatingSystemType::IOS`, `OperatingSystemType::Linux`, `OperatingSystemType::Android` und `OperatingSystemType::WindowsPhone`. |

<Tip>
  Jeder Besucher kann nur ein `OperatingSystem` haben. Das Hinzufügen eines zweiten `OperatingSystem` überschreibt das erste.
</Tip>

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {OperatingSystem{OperatingSystemType::Windows}});
```

#### PageView

Speichert Seitenaufruf-Events.

| Name | Typ | Beschreibung | Standard |
| - | - | - | - |
| `url` | `std::string` | URL der angesehenen Seite. | |
| `title` | `std::optional<std::string>` | Titel der angesehenen Seite. | `std::nullopt` |
| `referrers` | `std::vector<int32_t>` | Referrer-Indizes der zuvor angesehenen Seiten. | `{}` |

<Note>
  Der Referrer-Index ist in der Kameleoon-App auf der Seite [Konfiguration des Akquisitionskanals](/de/user-manual/assets/advanced-targeting-tools/create-an-acquisition-channel) verfügbar. Achtung: Der Index beginnt bei `0`, sodass der erste von Ihnen erstellte Akquisitionskanal die ID `0` hat, nicht `1`.
</Note>

```cpp theme={null}
using namespace kameleoon;

// Full initialization with url, title, and referrers
client.add_data(visitor_code, {PageView{.url = "https://example.com", .title = "Homepage", .referrers = {3}}});

// Minimal initialization, only requires a URL
client.add_data(visitor_code, {PageView{.url = "https://example.com"}});
```

#### UniqueIdentifier

Wenn Sie keinen `UniqueIdentifier` für einen Besucher hinzufügen, wird `visitor_code` als eindeutige Besucherkennung verwendet, was für die [Cross-Device-Experimentierung](/de/developer-docs/cross-device-experimentation) nützlich ist. Wenn Sie `UniqueIdentifier{true}` hinzufügen, verknüpft das SDK die geflushten Daten mit dem Besucher, der der angegebenen Kennung zugeordnet ist.

Dies kann in Situationen nützlich sein, in denen Sie nicht auf den anonymen `visitor_code` zugreifen können, der einem Besucher ursprünglich zugewiesen wurde, aber Zugriff auf eine interne Kennung haben, die diesem Besucher durch Sitzungszusammenführung zugeordnet ist.

| Name | Typ | Beschreibung |
| - | - | - |
| `value` | `bool` | Ob der aktuelle `visitor_code` als eindeutige Kennung behandelt werden soll. |

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {UniqueIdentifier{true}});
```

#### UserAgent

Serverseitige Experimente sind häufiger von Bot-Traffic betroffen als clientseitige Experimente. Kameleoon verwendet die IAB/ABC International Spiders and Bots List, um bekannte Bots und Spider zu erkennen, und verwendet auch das Feld `UserAgent`, um anderen unerwünschten Traffic herauszufiltern, der Ihre Conversion-Metriken verzerren könnte. Weitere Informationen finden Sie im Hilfeartikel zum [Bot-Filtering](/de/user-manual/experiment-analytics/troubleshooting/data-discrepancies#how-does-kameleoon-filter-bot-traffic-from-my-results).

Wenn Sie interne Bots verwenden, senden Sie den User-Agent-Wert `curl/8.0`, um sie von der Analytik auszuschließen.

| Name | Typ | Beschreibung |
| - | - | - |
| `value` | `std::string` | User-Agent-Wert, der mit Tracking-Anfragen gesendet wird. |

```cpp theme={null}
using namespace kameleoon;

client.add_data(visitor_code, {UserAgent{"Mozilla/5.0"}});
```

### Zurückgegebene Typen

#### DataFile

Das `DataFile` enthält die SDK-Konfigurationsdetails.

Es kann bei Bedarf mit zusätzlichen Informationen erweitert werden. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name | Typ | Beschreibung |
| - | - | - |
| `feature_flags` | `std::unordered_map<std::string, FeatureFlag>` | Eine Map von [`FeatureFlag`](#featureflag)-Objekten, indexiert nach Feature-Flag-Schlüsseln. |
| `date_modified` | `uint64_t` | Der Zeitstempel (in Millisekunden), der angibt, wann das `DataFile` zuletzt geändert wurde. |

```cpp 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.
const std::unordered_map<std::string, FeatureFlag>& feature_flags = datafile.feature_flags;

// Retrieves the last modification timestamp of the DataFile.
// The value is a uint64_t representing milliseconds since the Unix epoch.
uint64_t date_modified = datafile.date_modified;
```

#### 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 andere zugehörige Details).

Er kann bei Bedarf mit zusätzlichen Informationen erweitert werden. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name | Typ | Beschreibung |
| - | - | - |
| `environment_enabled` | `bool` | Gibt an, ob der Feature Flag in der aktuellen Umgebung aktiviert ist. |
| `default_variation_key` | `std::string` | Der Schlüssel der dem Feature Flag zugeordneten Standardvariation. |
| `variations` | `std::unordered_map<std::string, Variation>` | Eine Map von `Variation`-Objekten, indexiert nach Variationsschlüsseln. |
| `rules` | `std::vector<Rule>` | Eine Liste von `Rule`-Objekten |

```cpp theme={null}
// Check whether the feature flag is enabled in the current environment.
bool environment_enabled = feature_flag.environment_enabled;

// Retrieve the key of the default variation.
const std::string& default_variation_key = feature_flag.default_variation_key;

// Retrieve the default variation object (nullptr if the key isn't in `variations`).
const Variation* default_variation = feature_flag.default_variation();

// Retrieve all variations of the feature flag as a map (key = variation key, value = Variation object).
const std::unordered_map<std::string, Variation>& variations = feature_flag.variations;

// Retrieve all targeting rules associated with the feature flag.
const std::vector<Rule>& rules = feature_flag.rules;
```

#### Rule

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

Sie kann bei Bedarf mit zusätzlichen Informationen erweitert werden. Wenn Sie weitere Details benötigen, wenden Sie sich bitte an Ihren Customer Success Manager.

| Name | Typ | Beschreibung |
| - | - | - |
| `variations` | `std::unordered_map<std::string, Variation>` | Eine Map von `Variation`-Objekten, indexiert nach Variationsschlüsseln. |

```cpp theme={null}
// Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
const std::unordered_map<std::string, Variation>& variations = rule.variations;
```

#### Variation

`Variation` enthält Informationen über die dem Besucher zugewiesene Variation oder die Standardvariation, wenn keine spezifische Zuweisung vorhanden ist.

| Name | Typ | Beschreibung |
| - | - | - |
| `name` | `std::string` | Der Name der Variation. |
| `key` | `std::string` | Der eindeutige Schlüssel, der die Variation identifiziert. |
| `id` | `std::optional<uint32_t>` | Die ID der zugewiesenen Variation oder `std::nullopt` für eine Standardvariation. |
| `experiment_id` | `std::optional<uint32_t>` | Die ID des mit der Variation verbundenen Experiments oder `std::nullopt` für eine Standardvariation. |
| `variables` | `std::vector<Variable>` | Mit der Variation verbundene Variablen. Diese Sammlung kann leer sein, wenn keine Variablen angehängt sind. |

<Note>
  * `Variation` beschreibt die zugewiesene oder Standardvariation, während [`Variable`](#variable) die Details jeder einzelnen Variable enthält.
  * `id` und `experiment_id` können `std::nullopt` sein, was eine Standardvariation anzeigt, die nicht an eine bestimmte Experimentzuweisung gebunden ist.
</Note>

Zusätzliche Hilfsmethoden:

| Methode | Rückgabetyp | Beschreibung |
| - | - | - |
| `active()` | `bool` | Gibt `false` für die `off`-Variation zurück. |
| `get_variable(key)` | `const Variable*` | Gibt einen Zeiger auf die Variationsvariable mit dem angegebenen Schlüssel zurück oder `nullptr`, wenn sie nicht gefunden wurde. |

```cpp theme={null}
// Retrieving the variation name
const std::string& variation_name = variation.name;

// Retrieving the variation key
const std::string& variation_key = variation.key;

// Retrieving the variation id
std::optional<uint32_t> variation_id = variation.id;

// Retrieving the experiment id
std::optional<uint32_t> experiment_id = variation.experiment_id;

// Retrieving the variables vector
const std::vector<Variable>& variables = variation.variables;

// Checking if the variation is active (i.e., currently being served to visitors)
bool is_active = variation.active();

// Retrieving a variable by its key, returning `nullptr` if not found
if (const Variable* variable = variation.get_variable("title")) {
    // Use `variable`.
}
```

#### Variable

`Variable` enthält Informationen über eine Variable, die der zugewiesenen Variation zugeordnet ist.

| Name | Typ | Beschreibung |
| - | - | - |
| `key` | `std::string` | Der eindeutige Schlüssel, der die Variable identifiziert. |
| `kind` | `std::string` | Der Variablentyp. Mögliche Werte sind `BOOLEAN`, `NUMBER`, `STRING`, `JSON`, `JS` und `CSS`. |
| `value` | [`JsonValue`](#jsonvalue) | Der Wert der Variable. Je nach `kind` kann sie einen Booleschen Wert, eine Zahl, eine Zeichenkette, eine JSON-Zeichenkette, einen JavaScript-Codeschnipsel oder einen CSS-Codeschnipsel enthalten. |

```cpp theme={null}
// Retrieve the list of variables associated with the variation
const std::vector<Variable>& variables = variation.variables;

// Access the variable key
const std::string& variable_key = variable.key;

// Access the variable type (kind) for conditional handling
const std::string& kind = variable.kind;

// Extract the value as a number (returns `std::nullopt` if not a number)
std::optional<double> number = variable.value.as_number();

// Extract the value as a boolean (returns `std::nullopt` if not a boolean)
std::optional<bool> apply_discount = variable.value.as_bool();

// Extract the value as a string (returns `std::nullopt` if not a string-carrying kind)
std::optional<std::string> title = variable.value.as_string();
```

<a id="jsonvalue" />

##### JsonValue

`JsonValue` stellt den Wert einer Variationsvariable in C++ dar. Das Feld `kind` unterscheidet die zeichenkettentragenden Arten; `value` ist ein `std::variant<bool, double, std::string>`.

| Art | Gespeicherter Typ | Beschreibung |
| - | - | - |
| `JsonValueKind::Boolean` | `bool` | Stellt einen Booleschen Wert dar. |
| `JsonValueKind::Number` | `double` | Stellt einen numerischen Wert dar. |
| `JsonValueKind::String` | `std::string` | Stellt einen Zeichenkettenwert dar. |
| `JsonValueKind::JSON` | `std::string` | Stellt einen JSON-codierten Wert dar. |
| `JsonValueKind::JS` | `std::string` | Stellt einen JavaScript-Codeschnipsel dar. |
| `JsonValueKind::CSS` | `std::string` | Stellt einen CSS-Codeschnipsel dar. |

Typisierte Accessoren geben `std::nullopt` zurück, wenn der Wert von einer anderen Art ist:

| Methode | Rückgabetyp | Beschreibung |
| - | - | - |
| `as_bool()` | `std::optional<bool>` | Der Boolesche Wert. |
| `as_number()` | `std::optional<double>` | Der numerische Wert. |
| `as_string()` | `std::optional<std::string>` | Der Zeichenkettenwert für jede zeichenkettentragende Art (`String`, `JSON`, `JS` und `CSS`). |
