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

# iOS SDK

> Intégrez le SDK iOS de Kameleoon pour exécuter des expériences et activer des feature flags dans les applications iOS natives en Swift.

Avec le SDK iOS (Swift) de Kameleoon, vous pouvez exécuter des expériences et activer des feature flags sur les applications mobiles iOS natives. L'intégration du SDK dans les applications Swift est simple, et son empreinte (utilisation de la mémoire et du réseau) est faible.

**Démarrage** : Pour vous aider à démarrer, consultez le [guide développeur](#guide-développeur).

**Changelog** : Dernière version du SDK Swift : 4.27.2 [Changelog](https://github.com/Kameleoon/client-swift/blob/master/CHANGELOG.md).

**Méthodes du SDK** : Pour la documentation de référence complète des méthodes du SDK iOS, consultez la section [référence](#référence).

## Guide développeur

Suivez ces étapes pour installer et configurer le SDK iOS de Kameleoon dans votre application pour la première fois.

### Démarrage

#### Kit de démarrage

Pour faciliter le démarrage, Kameleoon fournit un kit de démarrage et une application de démonstration pour tester le SDK. Le kit de démarrage comprend une application entièrement configurée avec des exemples illustrant comment les méthodes du SDK peuvent être utilisées dans une application. Le kit de démarrage, l'application de démonstration et les instructions détaillées sont disponibles sur [Starter kit for iOS](https://github.com/Kameleoon/ios-examples)

#### Prérequis

* Utilisez Swift version 5.0 ou supérieure sur la plateforme iOS. La prise en charge des applications iOS antérieures (y compris les versions antérieures de Swift et les applications Objective-C) n'est pas prévue. Une version Universal Framework est disponible, compatible à la fois avec x86\_64 (pour le simulateur iOS) et ARM (pour le déploiement en production sur l'App Store).

#### Installation

Vous pouvez installer le SDK iOS en utilisant CocoaPods ou Swift Package Manager :

<Tabs defaultTabIndex={1}>
  <Tab title="CocoaPods">
    Avec <a href="https://guides.cocoapods.org/using/using-cocoapods.html">CocoaPods</a>, collez le code suivant dans votre Podfile et remplacez `YOUR_TARGET_NAME` par la valeur correspondant à votre application :

    ```swift theme={null}
    # Podfile
    use_frameworks!

    target 'YOUR_TARGET_NAME' do
      pod 'kameleoonClient'
    end
    ```

    Ensuite, dans une invite de commande, dans le répertoire du `Podfile`, exécutez la commande d'installation :

    ```custom_code theme={null}
    pod install
    ```
  </Tab>

  <Tab title="Swift Package Manager">
    Avec <a href="https://github.com/apple/swift-package-manager">Swift Package Manager</a>, ajoutez une <a href="https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app">dépendance de package à votre projet Xcode</a>. Sélectionnez **File > Swift Packages > Add Package Dependency** et entrez l'URL du dépôt : `https://github.com/Kameleoon/client-swift`.

    Alternativement, vous pouvez modifier directement votre fichier `Package.swift` :

    ```swift theme={null}
    dependencies: [
      .package(url: "https://github.com/Kameleoon/client-swift.git", from("3.0.3"))
    ]
    ```
  </Tab>
</Tabs>

***

#### Configuration supplémentaire

Pour personnaliser le comportement du SDK, créez un fichier de configuration `kameleoon-client-swift.plist` dans le répertoire racine de votre projet Xcode. Vous pouvez également [télécharger un exemple de configuration](/assets/developer-docs/sdks/mobile-sdks/client-configs/kameleoon-client-swift.plist).

Voici les clés que vous pouvez définir :

| Clé                                                                                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Valeur par défaut    |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| `refreshIntervalMinute` / `refresh_interval_minute` (*optionnel*)                              | Spécifie l'intervalle d'actualisation, en minutes, pendant lequel le SDK récupère la configuration des expériences actives et des feature flags. La valeur détermine le temps maximum nécessaire pour propager les modifications, telles que l'activation ou la désactivation des feature flags ou le lancement d'expériences. Si non spécifié, l'intervalle par défaut est de 60 minutes. De plus, un [mode streaming](/developer-docs/feature-experimentation/technical-reference/technical-considerations/#streaming-premium-option) est disponible, qui utilise les server-sent events (SSE) pour transmettre automatiquement les nouvelles configurations au SDK et les appliquer en temps réel.                                                                                                                                               | `60` minutes         |
| `dataExpirationIntervalMinute` / `data_expiration_interval_minute` (*optionnel*)               | Désigne la période prédéfinie, en minutes, pendant laquelle le SDK stocke le visiteur et ses données associées. Chaque instance de données est évaluée individuellement, vous permettant de définir la durée pendant laquelle le SDK enregistre les données avant de les supprimer automatiquement. Si aucun intervalle n'est spécifié, le SDK ne supprime pas automatiquement les données de l'appareil.                                                                                                                                                                                                                                                                                                                                                                                                                                           | `Date.distantFuture` |
| `defaultTimeoutMillisecond` / `default_timeout_millisecond` (*optionnel*)                      | Spécifie l'intervalle de temps, en millisecondes, nécessaire au délai d'expiration des requêtes réseau du SDK. Définissez la valeur sur `30000` millisecondes (30 secondes) ou plus si vous n'avez pas de connexion stable. Certaines méthodes ont des paramètres supplémentaires pour des délais d'expiration spécifiques à la méthode, mais si vous ne les spécifiez pas explicitement, la valeur par défaut est utilisée.                                                                                                                                                                                                                                                                                                                                                                                                                        | `10000` ms           |
| `trackingIntervalMillisecond` / `tracking_interval_millisecond` (*optionnel*)                  | Spécifie l'intervalle des requêtes de tracking, en millisecondes. Tous les visiteurs qui ont été évalués pour un feature flag ou dont les données ont été envoyées seront inclus dans cette requête de tracking, qui est exécutée une fois par intervalle. La valeur minimale est de `1000` ms et la valeur maximale est de `5000` ms.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `1000` ms            |
| `environment` / `environment` (*optionnel*)                                                    | Pour les clients utilisant l'expérimentation et le feature flagging multi-environnement, cette option spécifie quelle configuration de feature flag utiliser. Par défaut, chaque feature flag dispose des options `production`, `staging` et `development`. Si non spécifié, la valeur par défaut est `production`. [Plus d'informations](/user-manual/experimentation/feature-experimentation/configure-your-feature-flags/manage-environments).                                                                                                                                                                                                                                                                                                                                                                                                   | `nil`                |
| `isUniqueIdentifier` / `is_unique_identifier` (*optionnel*)                                    | Indique que le `visitorCode` spécifié est un identifiant unique.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | `false`              |
| `networkDomain` / `network_domain` (*optionnel*)                                               | Domaine personnalisé utilisé par les SDK pour les requêtes sortantes, souvent à des fins de proxy. Doit être un domaine valide (par exemple, example.com ou sub.example.com). Les formats invalides sont remplacés par la valeur par défaut de Kameleoon.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | `nil`                |
| `defaultDataFile` / `default_datafile` (*optionnel*)                                           | La fonctionnalité `default_datafile` garantit que le SDK Kameleoon est toujours **READY** en fournissant une configuration de repli lorsqu'aucun fichier de données mis en cache n'existe. Les développeurs peuvent précharger une configuration valide en la récupérant depuis `https://sdk-config.kameleoon.eu/v3/<sitecode>` et en la transmettant en tant que `default_datafile` lors de l'initialisation. Lorsqu'un timestamp `dateModified` (en millisecondes) est fourni et est plus récent que la version en cache, le SDK utilisera le datafile par défaut au lieu de la version en cache. **Si `dateModified` est omis, le datafile par défaut n'est appliqué que lorsqu'aucune version en cache n'existe**. Cela garantit que le SDK dispose toujours d'une configuration valide, qu'elle soit par défaut, mise en cache ou mise à jour. | `nil`                |
| `activityTrackingIntervalMillisecond` / `activity_tracking_interval_millisecond` (*optionnel*) | Définit la fréquence à laquelle le SDK envoie un événement d'activité pour prolonger la session du visiteur. Modifier ce paramètre peut avoir des effets secondaires — consultez [cette section](#using-activitytrackingintervalmillisecond) avant de l'ajuster. La valeur minimale et par défaut est de `60 000` ms ; toute valeur inférieure non nulle est ignorée et la valeur par défaut est appliquée. Définissez-la sur `0` pour désactiver le suivi périodique d'activité ; dans ce cas, un seul événement d'activité est envoyé au démarrage de l'application.                                                                                                                                                                                                                                                                              | `60 000` ms          |

<Note>
  Si vous spécifiez un `visitorCode` et définissez le paramètre `isUniqueIdentifier` sur `true`, les méthodes du SDK utilisent la valeur de `visitorCode` comme identifiant unique du visiteur, ce qui est utile pour l'[expérimentation cross-device](/developer-docs/cross-device-experimentation). Le SDK lie les données envoyées au visiteur associé à l'identifiant spécifié.

  Le `isUniqueIdentifier` peut être utile dans d'autres cas limites, par exemple lorsque vous ne pouvez pas accéder au `visitorCode` anonyme initialement attribué au visiteur, mais que vous avez accès à un identifiant interne lié au visiteur anonyme via la fusion de sessions.
</Note>

##### Utilisation de `activityTrackingIntervalMillisecond`

Le paramètre `activityTrackingIntervalMillisecond` permet de réduire l'utilisation du réseau et la consommation de batterie en contrôlant la fréquence à laquelle le SDK envoie un événement d'activité pour prolonger la session du visiteur sur la Data API. La valeur par défaut et la valeur minimale autorisée sont de `60 000` ms (60 secondes) ; toute valeur inférieure non nulle est ignorée et la valeur par défaut est appliquée. Les minuteries sont mises en pause lorsque l'application est en arrière-plan, l'intervalle ne progresse donc effectivement que lorsque l'application est au premier plan.

Examinez son impact sur les fonctionnalités suivantes :

1. **[Déclencheurs de temps écoulé](/user-manual/assets/triggers/create-a-trigger#visiting-behavior)**
   * Si le temps écoulé configuré est inférieur à l'intervalle de tracking, le déclencheur ne se déclenchera pas comme prévu.

2. **[Segments de temps écoulé](/user-manual/assets/segments/create-a-segment#visiting-behavior)**
   * Si le temps écoulé est inférieur à l'intervalle de tracking, les utilisateurs peuvent ne pas être inclus dans le segment comme prévu.

3. **[Objectifs de temps passé](/user-manual/assets/goals/create-a-goal#time-spent)**
   * Si le temps écoulé est inférieur à l'intervalle de tracking, l'objectif peut ne jamais être atteint.

4. **[Temps écoulé depuis la dernière visite dans la page de résultats](/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#filter-audience)**
   * Les mesures du « temps écoulé depuis la dernière visite » deviennent moins précises lorsque le temps écoulé est proche ou inférieur à l'intervalle de tracking.

5. **[Nombre de visites](/user-manual/experiment-analytics/troubleshooting/data-discrepancies#how-visits-and-visitors-are-counted)**
   * Une nouvelle visite est créée après 30 minutes d'inactivité. Si l'intervalle de tracking est supérieur à 30 minutes, une nouvelle visite sera créée à chaque intervalle de tracking.

<Warning>
  Définir `activityTrackingIntervalMillisecond` sur `0` désactive entièrement le suivi périodique de l'activité. Dans cette configuration, un seul événement d'activité est envoyé au démarrage de l'application, ce qui rend inutilisables toutes les fonctionnalités énumérées ci-dessus.
</Warning>

#### Initialiser le Client Kameleoon

Après avoir configuré le SDK dans votre application, vous devez créer le Client Kameleoon. Un Client est un objet singleton qui agit comme un pont entre votre application et la plateforme Kameleoon. Il comprend toutes les méthodes et propriétés dont vous avez besoin pour exécuter une expérience.

```swift theme={null}
import kameleoonClient

let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
    // pass client configuration as an argument
    let config = try KameleoonClientConfig(
        clientId: "clientId", // optional
        clientSecret: "clientSecret", // optional
        refreshIntervalMinute: 15, // optional, 60 minutes by default
        dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
        defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
        trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
        environment: "production", // optional
        isUniqueIdentifier: false, // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
        networkDomain: "example.com", // optional, nil by default
        defaultDataFile: "{...}", // optional, nil by default
        activityTrackingIntervalMillisecond: 20_000 // optional, 15_000 milliseconds by default
    )
    let kameleoonClient = try KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: visitorCode, // optional
        config: config // optional
    )
} catch KameleoonError.visitorCodeInvalid {
  // Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
  // Indicates that provided site code is empty
} catch {
    // Unexpected error occurred
}

do {
    // read client configuration from a file 'kameleoon-client-swift.plist'
    // visitor code isn't provided, so SDK generates a random visitor code which it will use in the future
    let kameleoonClient = try KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
    // Provided visitor code is invalid
} catch {
    // Unexpected error occurred
}
```

La méthode `KameleoonClientFactory.create()` initialise le client, mais le client n'est pas immédiatement prêt à être utilisé. Le client doit récupérer la configuration actuelle des expériences et des feature flags (ainsi que leur répartition de trafic) auprès d'un serveur distant Kameleoon. Cette récupération nécessite que le client ait accès au réseau, ce qui n'est pas toujours disponible. Tant que le Client Kameleoon n'est pas entièrement prêt, vous ne devez pas tenter d'exécuter d'autres méthodes du SDK iOS de Kameleoon. Une fois que le client a récupéré la première configuration des feature flags, il actualise périodiquement la configuration. Si l'actualisation échoue pour une raison quelconque, le client Kameleoon continue de fonctionner en utilisant la configuration précédente.

Vous pouvez utiliser le getter public `.ready` pour vérifier si l'initialisation du client Kameleoon est terminée.

Alternativement, un **callback d'aide** peut encapsuler la logique de déclenchement de l'expérience et de mise en œuvre de la variation. La meilleure approche (`.ready` ou **callback**) dépend des préférences et du cas d'usage. Utiliser `.ready` est recommandé lorsque le SDK est censé être prêt à l'emploi rapidement. Par exemple, `.ready` est approprié lors de l'exécution d'une expérience sur une boîte de dialogue qui ne serait accessible qu'après quelques secondes ou minutes de navigation dans l'application. Un callback est recommandé lorsqu'il existe une forte probabilité que le SDK soit encore en cours d'initialisation lorsque l'expérience est atteinte. Par exemple, une expérience visible au lancement de l'application devrait utiliser un callback qui fait attendre l'application jusqu'à ce que le SDK soit prêt ou qu'un délai spécifié soit expiré.

<Note>
  Il est de votre responsabilité, en tant que développeur de l'application, de vous assurer que le client est prêt avant d'appeler une méthode. Une bonne pratique consiste à toujours supposer que l'utilisateur de l'application doit être exclu de l'expérience si le client Kameleoon n'est pas encore prêt. Cette exclusion est facile à réaliser, car elle correspond à la mise en œuvre de la logique de variation de référence par défaut comme indiqué dans l'exemple de code ci-dessus.
</Note>

Vous êtes maintenant prêt à mettre en œuvre la gestion des fonctionnalités et les feature flags. Consultez la section [Référence](#référence) pour plus de détails sur les méthodes supplémentaires.

#### Bonnes pratiques pour l'initialisation et l'utilisation

* Il est recommandé d'initialiser [`KameleoonClient`](#create) en tant que singleton dès que possible après le démarrage de l'application, car l'initialisation peut prendre un certain temps. L'initialisation étant asynchrone, elle ne bloque ni ne retarde le processus de démarrage de l'application.
* Avant d'utiliser `KameleoonClient`, vérifiez qu'il est initialisé en appelant la méthode [`runWhenReady`](#runwhenready). Sinon, les tentatives d'utilisation du client avant qu'il ne soit prêt entraîneront des erreurs.
* ⚠️ La plupart des méthodes clés peuvent lever des erreurs, une gestion appropriée des exceptions est donc requise. Assurez-vous de consulter la documentation de chaque méthode que vous utilisez pour comprendre ses erreurs potentielles.

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    do {
        let kameleoonClient = try KameleoonClientFactory.create(siteCode: "<siteCode>");
    } catch {}

    // Example: Apply a discount percentage based on an feature flag variable's value
    func applyDiscountIfApplicable() {
        client.runWhenReady(timeoutMilliseconds: 1000) { ready in
            guard ready else { return }
            if let variation = try? client.getVariation(featureKey: "discount"),
               let discount = variation.variables["discount_value"]?.value as? Double {
                applyDiscount(value: discount)
            }
        }
    }
    ```
  </Tab>

  <Tab title="Swift (Async)">
    ```swift theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    do {
        let kameleoonClient = try KameleoonClientFactory.create(siteCode: "<siteCode>");
    } catch {}

    // Example: Apply a discount percentage based on an feature flag variable's value
    func applyDiscountIfApplicable() async throws {
        try await client.runWhenReady(timeoutMilliseconds: 1000)
        if let variation = try client.getVariation(featureKey: "discount"),
           let discount = variation.variables["discount_value"]?.value as? Double {
            applyDiscount(value: discount)
        }
    }
    ```
  </Tab>
</Tabs>

#### Activer un feature flag

##### Récupérer la configuration d'un flag

Pour mettre en œuvre un feature flag dans votre code, vous devez d'abord créer le feature flag dans votre compte Kameleoon.

Pour déterminer le statut ou la variation d'un feature flag pour un utilisateur spécifique, vous devez utiliser la méthode [`getVariation()`](#getvariation) ou [`isFeatureActive()`](#isfeatureactive) pour récupérer la configuration en fonction de la `featureKey`.

La méthode `getVariation()` gère à la fois les feature flags simples avec des états ON/OFF et les flags plus complexes avec plusieurs variations. La méthode récupère la variation appropriée pour l'utilisateur en vérifiant les règles de la fonctionnalité, en attribuant la variation et en la renvoyant en fonction de la `featureKey` et du `visitorCode`.

La méthode `isFeatureActive()` peut être utilisée si vous souhaitez récupérer la configuration d'un feature flag simple qui n'a qu'un état ON ou OFF, par opposition à des feature flags plus complexes avec plusieurs variations ou options de ciblage.

Si votre feature flag a des variables associées (telles que des comportements spécifiques liés à chaque variation), `getVariation()` vous permet également d'accéder à l'objet [`Variation`](#variation), qui fournit des détails sur la variation attribuée et son expérience associée. Cette méthode vérifie si l'utilisateur est ciblé, trouve la variation attribuée au visiteur et l'enregistre dans le stockage. Lorsque `track=true`, le SDK enverra l'événement d'exposition à l'expérience spécifiée lors de la prochaine requête de tracking, qui est automatiquement déclenchée en fonction de l'intervalle [`tracking_interval_millisecond`](#configuration-supplémentaire) du SDK. Par défaut, cet intervalle est défini sur 1000 millisecondes (1 seconde).

La méthode `getVariation()` vous permet de contrôler si le tracking est effectué. Si `track=false`, aucun événement d'exposition ne sera envoyé par le SDK. Cela est utile si vous préférez ne pas suivre les données via le SDK et plutôt vous appuyer sur le tracking côté client géré par le moteur Kameleoon, par exemple. De plus, définir `track=false` est utile lors de l'utilisation de la méthode `getVariations()`, où vous pourriez avoir besoin uniquement des variations pour tous les flags sans déclencher d'événements de tracking. Si vous souhaitez en savoir plus sur le fonctionnement du tracking, consultez [cet article](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics)

##### Ajouter des points de données pour cibler un utilisateur ou filtrer / décomposer les visites dans les rapports

Pour cibler un utilisateur, assurez-vous d'avoir ajouté les points de données pertinents à son profil avant de récupérer la variation de la fonctionnalité ou de vérifier si le flag est actif. Utilisez la méthode [`addData()`](#adddata) pour ajouter ces points de données au profil de l'utilisateur.

Pour récupérer les points de données collectés sur d'autres appareils, utilisez la méthode [`getRemoteVisitorData()`](#getremotevisitordata). Cette méthode récupère de manière asynchrone les données depuis les serveurs. Il est important d'appeler `getRemoteVisitorData()` *avant* de récupérer la variation ou de vérifier si le feature flag est actif, car ces données peuvent être requises pour attribuer un utilisateur à une variation donnée.

Pour en savoir plus sur les conditions de ciblage disponibles, consultez l'[article détaillé sur le sujet](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

De plus, les points de données que vous ajoutez au profil du visiteur seront disponibles lors de l'analyse de vos expériences, vous permettant de filtrer et de décomposer vos résultats par facteurs comme l'appareil. Consultez la liste complète [ici](/fr/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#ventiler-l’audience).

Si vous devez suivre des points de données supplémentaires au-delà de ce qui est collecté automatiquement, vous pouvez utiliser la [fonctionnalité Custom Data](#customdata) de Kameleoon. Custom Data vous permet de capturer et d'analyser des informations spécifiques pertinentes pour vos expériences. N'oubliez pas d'appeler la méthode [`flush()`](#flush) pour envoyer les données collectées aux serveurs Kameleoon pour analyse.

##### Suivre les conversions d'objectifs

Lorsqu'un utilisateur effectue une action souhaitée (comme effectuer un achat), elle est enregistrée comme une conversion. Pour suivre les conversions, utilisez la méthode [`trackConversion()`](#trackconversion) et fournissez le paramètre `goalId` requis.

La requête de suivi de conversion sera envoyée avec la prochaine requête de tracking programmée, que le SDK envoie à intervalles réguliers (définis par [`tracking_interval_millisecond`](#configuration-supplémentaire)). Si vous préférez envoyer la requête immédiatement, utilisez la méthode [`flush()`](#flush) avec le paramètre `instant=true`.

### Expérimentation cross-device

Pour prendre en charge les visiteurs qui accèdent à une application depuis plusieurs appareils, Kameleoon permet la synchronisation des données de visiteur précédemment collectées sur chacun des appareils du visiteur et la réconciliation de leur historique de visite entre appareils grâce à l'expérimentation cross-device. Des études de cas et des informations détaillées sur la façon dont Kameleoon gère les données entre appareils sont disponibles dans l'[article sur l'expérimentation cross-device](/developer-docs/cross-device-experimentation).

#### Synchroniser les custom data entre appareils

Bien que la synchronisation de mapping personnalisé soit utilisée pour aligner les données de visiteur entre appareils, ce n'est pas toujours nécessaire. Voici deux scénarios où la synchronisation de mapping personnalisé n'est pas requise :

**Même ID utilisateur sur tous les appareils**
Si le même ID utilisateur est utilisé de manière cohérente sur tous les appareils, la synchronisation est gérée automatiquement sans synchronisation de mapping personnalisé. Il suffit d'appeler la méthode `getRemoteVisitorData()` lorsque vous souhaitez synchroniser les données collectées entre plusieurs appareils.

**Instances multi-serveurs avec des ID cohérents**
Dans des configurations complexes impliquant plusieurs serveurs (par exemple, des instances de serveur distribuées), où le même ID utilisateur est disponible sur les serveurs, la synchronisation entre serveurs (avec `getRemoteVisitorData()`) est suffisante sans synchronisation supplémentaire de mapping personnalisé.

Les clients qui ont besoin de données supplémentaires peuvent se référer à la description de la méthode [`getRemoteVisitorData()`](#getremotevisitordata) pour plus d'informations. Dans le code ci-dessous, il est supposé que le même identifiant unique (dans ce cas, le `visitorCode`, qui peut également être désigné comme `userId`) est utilisé de manière cohérente entre les deux appareils pour une récupération précise des données.

<Note>
  Si vous souhaitez synchroniser les données collectées en temps réel, vous devez choisir la portée **Visitor** pour vos custom data.
</Note>

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift title="Device A" theme={null}
    // In this example, Custom data with index `90` was set to "Visitor" scope in Kameleoon.
    let visitorScopeCustomDataIndex = 90

    kameleoonClient.addData(CustomData(id: visitorScopeCustomDataIndex, values: "your data"))
    kameleoonClient.flush()
    ```

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

  <Tab title="Swift (Async)">
    ```swift title="Device A" theme={null}
    // In this example, Custom data with index `90` was set to "Visitor" scope in Kameleoon.
    let visitorScopeCustomDataIndex = 90

    kameleoonClient.addData(CustomData(id: visitorScopeCustomDataIndex, values: "your data"))
    kameleoonClient.flush()
    ```

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

#### Utiliser des custom data pour la fusion de sessions

L'[expérimentation cross-device](/developer-docs/cross-device-experimentation) permet de combiner l'historique d'un visiteur sur chacun de ses appareils (réconciliation d'historique). La réconciliation d'historique permet de fusionner différentes sessions de visiteur en une seule. Pour réconcilier l'historique de visite, utilisez [`CustomData`](#customdata) pour fournir un identifiant unique au visiteur. Pour plus d'informations, consultez la [documentation dédiée](/developer-docs/cross-device-experimentation/#activating-cross-device-history-reconciliation).

Une fois la réconciliation cross-device activée, l'appel de [`getRemoteVisitorData()`](#getremotevisitordata) avec le paramètre `userId` récupère toutes les données connues pour un utilisateur donné.

Les sessions avec le même identifiant verront toujours la même variation dans une expérience. Dans la vue Visiteur des pages de résultats de votre expérience, ces sessions apparaîtront comme un seul visiteur.

La configuration du SDK garantit que les sessions associées voient toujours la même variation de l'expérience. Cependant, il existe certaines limitations concernant l'allocation de variation cross-device. Ces limitations sont décrites [ici](/developer-docs/cross-device-experimentation#critical-points-and-practical-insights).

Suivez le guide [d'activation de la réconciliation d'historique cross-device](#expérimentation-cross-device) pour configurer vos custom data sur la plateforme Kameleoon.

Ensuite, vous pouvez utiliser le SDK normalement. Voici les méthodes qui peuvent être utiles dans le contexte de la fusion de sessions :

* `getRemoteVisitorData()` avec `isUniqueIdentifier=true` passé à [`KameleoonClientConfig`](#configuration-supplémentaire) - pour récupérer les données de tous les visiteurs liés.
* [`trackConversion()`](#trackconversion) ou [`flush()`](#flush) avec `isUniqueIdentifier=true` passé à `KameleoonClientConfig` - pour suivre certaines données pour un visiteur spécifique associé à un autre visiteur.

<Tip>
  Comme les custom data que vous utilisez comme identifiant doivent être définies avec la portée **Visitor**, vous devez utiliser la [synchronisation des custom data cross-device](/developer-docs/cross-device-experimentation) pour récupérer l'identifiant avec la méthode [`getRemoteVisitorData()`](#getremotevisitordata) sur chaque appareil.
</Tip>

Voici un exemple d'utilisation des custom data pour la fusion de sessions.

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    // In this example, `91` represents the Custom Data's index,
    // configured as a unique identifier in Kameleoon.
    let mappingIndex = 91;
    let featureKey = "ff123";

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for the visitor.
    let anonymousKameleoonClient = KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: anonymousVisitorCode
    )
    anonymousKameleoonClient.runWhenReady { result in
        // ...
    }

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    let anonymousVariation = anonymousKameleoonClient.getVariation(featureKey)

    // 2. After the visitor is authenticated

    // Assume `userId` is the visitor code of the authenticated visitor.
    anonymousKameleoonClient.addData(CustomData(id: mappingIndex, values: userId))
    anonymousKameleoonClient.flush(instant: true)

    KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: userId,
        config: KameleoonClientConfig(
            isUniqueIdentifier: true // Indicate that `userId` is a unique identifier
        )
    )
    userKameleoonClient.runWhenReady { result in
        // ...
    }

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    let userVariation = userKameleoonClient.getVariation(featureKey: featureKey)
    let isSameVariation = userVariation.key == anonymousVariation.key // true

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

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

  <Tab title="Swift (Async)">
    ```swift theme={null}
    // In this example, `91` represents the Custom Data's index,
    // configured as a unique identifier in Kameleoon.
    let mappingIndex = 91;
    let featureKey = "ff123";

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for the visitor.
    let anonymousKameleoonClient = KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: anonymousVisitorCode
    )
    try await anonymousKameleoonClient.runWhenReady()

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    let anonymousVariation = anonymousKameleoonClient.getVariation(featureKey)

    // 2. After the visitor is authenticated

    // Assume `userId` is the visitor code of the authenticated visitor.
    anonymousKameleoonClient.addData(CustomData(id: mappingIndex, values: userId))
    anonymousKameleoonClient.flush(instant: true)

    KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: userId,
        config: KameleoonClientConfig(
            isUniqueIdentifier: true // Indicate that `userId` is a unique identifier
        )
    )
    try await userKameleoonClient.runWhenReady()

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    let userVariation = userKameleoonClient.getVariation(featureKey: featureKey)
    let isSameVariation = userVariation.key == anonymousVariation.key // true

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

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

Dans cet exemple, l'application possède une page de connexion. Puisque l'ID utilisateur est inconnu au moment de la connexion, un visiteur anonyme généré automatiquement par le SDK est utilisé. Le visitor code peut être récupéré avec la méthode [`getVisitorCode()`](#getvisitorcode). Une fois que l'utilisateur s'est connecté, le visiteur anonyme est associé à l'ID utilisateur et utilisé comme identifiant unique pour le visiteur.

### Utiliser une clé de bucketing personnalisée

Par défaut, Kameleoon utilise un ID visiteur unique et anonyme (`visitorCode`) pour attribuer les utilisateurs aux variations de feature flag. Cet ID est généralement généré et stocké sur l'appareil de l'utilisateur (dans un cookie de navigateur pour les SDK côté client et côté serveur — dans le stockage persistant pour les SDK mobiles). Cependant, dans certains scénarios, vous pouvez avoir besoin de vous assurer que tous les utilisateurs de la même organisation voient la même variante d'un feature flag.

L'option **Custom Bucketing Key** vous permet de remplacer ce comportement par défaut en fournissant votre propre identifiant personnalisé pour le bucketing. Ce remplacement garantit que la logique d'attribution de Kameleoon utilise la clé que vous avez spécifiée au lieu du `visitorCode` par défaut.

#### Cas d'usage

L'utilisation d'une clé de bucketing personnalisée est essentielle pour maintenir la cohérence et l'exactitude de vos attributions de feature flag, notamment dans ces situations :

* **Expériences au niveau du compte ou de l'organisation :** Pour les produits B2B ou les scénarios où vous souhaitez attribuer tous les utilisateurs de la même organisation à la même variation, vous pouvez utiliser un identifiant comme un `accountId`. Les clés de bucketing personnalisées sont cruciales pour les A/B tests de fonctionnalités qui impactent toute une équipe ou une entreprise.

En mettant en œuvre une clé de bucketing personnalisée, vous garantissez une plus grande cohérence et exactitude dans vos expériences, conduisant à des résultats plus fiables et une meilleure expérience utilisateur.

#### Détails techniques

Lorsque vous configurez une clé de bucketing personnalisée pour un feature flag, vous fournissez à Kameleoon un identifiant spécifique provenant des données de votre application :

```swift theme={null}
try? kameleoonClient.addData(CustomData(id: index, values: "newVisitorCode"))
```

* **Fournir la clé personnalisée :** Vous fournissez votre identifiant personnalisé au SDK Kameleoon en utilisant la méthode [`addData()`](#adddata). Dans cette méthode, vous passerez votre clé de bucketing personnalisée choisie en tant qu'objet [`CustomData`](#customdata). Ici, `newVisitorCode` fait référence à l'identifiant que vous souhaitez utiliser pour votre bucketing (par exemple, le nouveau `userId` ou `accountId`).

<Warning>
  Pour que la clé de bucketing personnalisée fonctionne correctement, elle doit également être définie et configurée pour le feature flag lors du processus de création ou de modification du flag. Sans cette configuration correspondante, le bucketing du SDK n'appliquera pas votre clé personnalisée. Pour des instructions détaillées sur la façon de configurer cela dans Kameleoon, consultez cet [article](/user-manual/experimentation/feature-experimentation/create-and-manage-flags/create-a-feature-flag#Advanced_Flag_Settings).
</Warning>

* **Logique de bucketing :** Une fois qu'une clé de bucketing personnalisée est fournie via la méthode `addData()`, tous les calculs de hachage pour attribuer les utilisateurs aux variations utiliseront ce `newVisitorCode` (votre clé personnalisée) au lieu du `visitorCode` par défaut. L'utilisation du `newVisitorCode` signifie que la décision de bucketing est liée à votre identifiant personnalisé, garantissant des attributions cohérentes dans divers contextes où cet identifiant est présent.
* **Suivi des données et analytique :** Il est crucial de noter que bien que le `newVisitorCode` (votre clé personnalisée) soit utilisé pour les décisions de bucketing, **toutes les données ultérieures (événements de tracking et conversions, par exemple) sont envoyées et associées au `visitorCode` *original*.** Cette séparation garantit que vos analyses reflètent avec précision les parcours utilisateur individuels et les interactions dans le contexte plus large de votre expérience, même lorsque le bucketing est effectué à un niveau supérieur (comme un compte) ou sur plusieurs appareils/sessions. Vos données de visiteur originales restent intactes pour un reporting complet.

#### Exigences techniques

Pour utiliser efficacement une clé de bucketing personnalisée :

* La clé doit être une `String`.
* Elle doit être unique pour l'entité que vous souhaitez bucketer (par exemple, si vous utilisez un `userId`, l'ID de chaque utilisateur doit être unique).
* La clé doit être disponible pour le SDK au moment exact où la décision du feature flag est évaluée pour cet utilisateur ou cette requête.

### Conditions de ciblage

Les SDK Kameleoon prennent en charge une variété de conditions de ciblage prédéfinies que vous pouvez utiliser pour cibler les utilisateurs dans vos campagnes. Pour la liste des conditions prises en charge par ce SDK, consultez [utiliser l'historique de visite pour cibler les utilisateurs](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

Vous pouvez également utiliser vos propres [données externes pour cibler les utilisateurs](/developer-docs/apis/data-api-rest/tutorials/storing-and-retrieving-external-data-to-target-users).

### Logging

Le SDK génère des logs pour refléter divers processus et problèmes internes.

#### Niveaux de log

Le SDK prend en charge la configuration de la limitation du logging par niveau de log.

```swift theme={null}
// The `none` log level does not allow logging.
KameleoonLogger.logLevel = .none

// The `ERROR` log level only allows logging issues that may affect the SDK's main behaviour.
KameleoonLogger.logLevel = .error

// The `WARNING` log level allows logging issues which may require additional attention.
// It extends the `ERROR` log level.
// The `WARNING` log level is a default log level.
KameleoonLogger.logLevel = .warning

// The `INFO` log level allows logging general information on the SDK's internal processes.
// It extends the `WARNING` log level.
KameleoonLogger.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 support
// to assist with internal troubleshooting.
KameleoonLogger.logLevel = .debug
```

#### Gestion personnalisée des logs

Le SDK écrit ses logs vers la sortie console par défaut. Ce comportement peut être remplacé.

<Note>
  La limitation du logging par niveau de log est effectuée indépendamment de la logique de gestion des logs.
</Note>

```swift theme={null}
public struct CustomLogger: Logging {
    let customLogger = Logger(subsystem: "com.yourcompany.app", category: "app")

    public func log(level: LogLevel, message: String) {
        switch level {
            case .error:
                customLogger.error("\(message)")
            case .warning:
                customLogger.warning("\(message)")
            case .info:
                customLogger.info("\(message)")
            case .debug:
                customLogger.debug("\(message)")
            default:
                break
        }
    }
}


// Log level filtering is applied separately from log handling logic.
// The custom logger will only accept logs that meet or exceed the specified log level.
// Ensure the log level is set correctly.
KameleoonLogger.logLevel = .debug // Optional, defaults to `LogLevel.WARNING`.
KameleoonLogger.logger = CustomLogger()
```

### Transmettre le visitor code à une WebView

Dans certains cas, vous devrez peut-être transmettre le **visitor code** de l'application native à une WebView qui utilise [Engine.js](/developer-docs/web-experimentation/implementation-and-deployment/standard-implementation) ou les SDK web [JavaScript](/developer-docs/sdks/web-sdks/js-sdk) ou [React](/developer-docs/sdks/web-sdks/react-js-sdk). L'exemple suivant illustre la méthode recommandée pour y parvenir :

<Tabs defaultTabIndex={0}>
  <Tab title="SwiftUI">
    ```swift theme={null}
    struct WebView: UIViewRepresentable {

        let url: URL
        let kameleoonClient: KameleoonClient

        private let kameleoonCookieName = "kameleoonVisitorCode"

        func makeUIView(context: Context) -> WKWebView {
            let config = WKWebViewConfiguration()
            let webView = WKWebView(frame: .zero, configuration: config)
            let cookieStore = webView.configuration.websiteDataStore.httpCookieStore
            let cookie = makeVisitorCookie()

            cookieStore.setCookie(cookie) {
                webView.load(URLRequest(url: url))
            }

            return webView
        }

        func updateUIView(_ webView: WKWebView, context: Context) {}

        private func makeVisitorCookie() -> HTTPCookie {
            let properties: [HTTPCookiePropertyKey: Any] = [
                .domain: ".example.com",
                .path: "/",
                .name: kameleoonCookieName,
                .value: kameleoonClient.visitorCode,
                .secure: true,
                .expires: Date(timeIntervalSinceNow: 60 * 60 * 24 * 365)
            ]
            return HTTPCookie(properties: properties)!
        }
    }
    ```
  </Tab>

  <Tab title="SwiftUI (iOS 26+)">
    ```swift theme={null}
    struct WebView: View {

        let url: URL
        let kameleoonClient: KameleoonClient

        private let websiteDataStore: WKWebsiteDataStore

        private let kameleoonCookieName = "kameleoonVisitorCode"

        @State private var page: WebPage

        init(url: URL, kameleoonClient: KameleoonClient) {
            self.url = url
            self.kameleoonClient = kameleoonClient

            let websiteDataStore = WKWebsiteDataStore.default()
            var configuration = WebPage.Configuration()
            configuration.websiteDataStore = websiteDataStore

            self.websiteDataStore = websiteDataStore
            _page = State(initialValue: WebPage(configuration: configuration))
        }

        var body: some View {
            WebView(page)
                .webViewBackForwardNavigationGestures(.enabled)
                .task(id: url) {
                    let cookieStore = websiteDataStore.httpCookieStore
                    let properties: [HTTPCookiePropertyKey: Any] = [
                        .domain: ".example.com",
                        .path: "/",
                        .name: kameleoonCookieName,
                        .value: kameleoonClient.visitorCode,
                        .secure: true
                    ]

                    if let cookie = HTTPCookie(properties: properties) {
                        await cookieStore.setCookie(cookie)
                    }

                    page.load(URLRequest(url: url))
                }
        }
    }
    ```
  </Tab>
</Tabs>

### Conformité à la confidentialité Apple

À partir du 1er mai 2024, Apple exige que les applications qui incluent un SDK tiers, tel que le SDK iOS Kameleoon, incluent un fichier manifeste de confidentialité. La dernière version du SDK est signée par code, conforme et comprend un fichier manifeste valide avec le SDK. Aucune action n'est requise si vous utilisez la version 4.2 ou ultérieure du SDK iOS de Kameleoon.

## Référence

Voici la documentation de référence complète pour le SDK iOS (Swift) de Kameleoon.

### Initialisation

Une fois que vous avez [installé le SDK](#installation) dans votre application, vous devez initialiser Kameleoon. Toutes les interactions de votre application avec le SDK, telles que le déclenchement d'une expérience, sont accomplies en utilisant cet objet client Kameleoon.

#### create()

Appelez cette méthode avant toute autre pour initialiser le SDK. Cette méthode se trouve dans `KameleoonClientFactory`. `create()` crée une instance de `KameleoonClient` pour gérer toutes les interactions entre le SDK et votre application.

Vous pouvez personnaliser le comportement du SDK (par exemple, l'environnement, les identifiants) en fournissant un [objet de configuration](#configuration-supplémentaire). Sinon, le SDK essaie de trouver votre fichier de configuration et l'utilisera à la place.

```swift theme={null}
let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
    // pass client configuration as an argument
    let config = try KameleoonClientConfig(
        clientId: "clientId", // optional
        clientSecret: "clientSecret", // optional
        refreshIntervalMinute: 15, // optional, 60 minutes by default
        dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
        defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
        trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
        environment: "production", // optional
        isUniqueIdentifier: false, // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
        networkDomain: "example.com", // optional, nil by default
        defaultDataFile: "{...}", // optional, nil by default
        activityTrackingIntervalMillisecond: 20_000 // optional, 15_000 milliseconds by default
    )
    let kameleoonClient = try KameleoonClientFactory.create(
        siteCode: siteCode,
        visitorCode: visitorCode, // optional
        config: config // optional
    )
} catch KameleoonError.visitorCodeInvalid {
  // Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
  // Indicates that provided site code is empty
} catch {
    // Unexpected error occurred
}

do {
    // read client configuration from a file 'kameleoon-client-swift.plist'
    // visitor code isn't provided, so SDK generates a random visitor code which will be used in the future
    let kameleoonClient = KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
  // Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
  // Indicates that provided site code is empty
} catch {
    // Unexpected error occurred
}
```

##### Arguments

| Nom                       | Type                     | Description                                                                                                                                                                                                                                                                    | Par défaut |
| ------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| siteCode (*requis*)       | `String`                 | Une [clé unique](/user-manual/faq#how-do-i-find-my-sitecode) identifiant le projet Kameleoon utilisé avec le SDK.                                                                                                                                                              |            |
| visitorCode (*optionnel*) | `String?`                | Un identifiant de visiteur optionnel. S'il est disponible, utilisez votre **ID utilisateur** interne ; sinon, le SDK en générera un automatiquement.                                                                                                                           | `nil`      |
| config (*optionnel*)      | `KameleoonClientConfig?` | Configuration optionnelle du SDK. Si fournie, elle est utilisée à la place de la lecture d'un [fichier de configuration](#configuration-supplémentaire) externe. Si non fournie, le SDK tente de lire le fichier, mais s'il est absent, il revient au comportement par défaut. | `nil`      |

##### Valeur de retour

| Type              | Description                                                                                                                          |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `KameleoonClient` | Une instance de la classe `KameleoonClient` que votre application peut ensuite utiliser pour gérer vos expériences et feature flags. |

##### Exceptions levées

| Type                                | Description                                                                                                           |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `KameleoonError.visitorCodeInvalid` | Exception indiquant que le visitor code fourni n'est pas valide. Il est soit vide, soit plus long que 255 caractères. |
| `KameleoonError.siteCodeIsEmpty`    | Exception indiquant que le site code spécifié est une chaîne vide, ce qui est une valeur invalide.                    |

#### ready

Pour les SDK mobiles, l'initialisation du Client Kameleoon n'est pas immédiate. Le SDK doit effectuer un appel serveur pour récupérer la configuration actuelle de toutes les expériences actives. Vérifiez si le SDK est prêt en appelant cette méthode avant de déclencher une expérience. Alternativement, vous pouvez utiliser la méthode [`runWhenReady()`](#runwhenready) avec un callback.

```swift theme={null}
let ready = kameleoonClient.ready
```

##### Valeur de retour

| Nom   | Type | Description                                                                                                             |
| ----- | ---- | ----------------------------------------------------------------------------------------------------------------------- |
| ready | Bool | Booléen représentant le statut du SDK (true s'il est entièrement initialisé, false s'il n'est pas prêt à être utilisé). |

#### runWhenReady()

* 🔄 *Effectue une requête asynchrone (si la configuration est obsolète ou manquante)*

Pour les SDK mobiles, le `KameleoonClient` ne peut pas s'initialiser immédiatement, car il doit effectuer un appel serveur pour récupérer la configuration actuelle de tous les feature flags. Utilisez la méthode [`runWhenReady()`](#runwhenready) pour attendre que le client soit prêt à l'emploi. De plus, vous pouvez définir une période maximale de timeout pour contrôler combien de temps le client attendra avant d'être prêt.

Si `ready=true`, le `KameleoonClient` est entièrement initialisé, et les feature flags seront évalués et se verront attribuer leurs variations respectives. Si le résultat est `false` ou si un timeout se produit, l'initialisation ne se terminera pas.

Le callback ou le code asynchrone doit gérer l'application de la variation de référence, car un timeout exclura l'utilisateur du feature flag.

<Warning>
  Étant donné que la configuration initiale peut nécessiter un appel serveur, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` en tant qu'argument à la méthode pour vous assurer d'être notifié lorsque le `KameleoonClient` est entièrement initialisé et prêt à l'emploi.
  * Utiliser des opérations asynchrones.
</Warning>

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    func applyRecommendedProductsVariation() {
        let defaultValue = 5 // Default control number for recommended products
        kameleoonClient.runWhenReady(timeoutMilliseconds: 1000) { ready in
            guard ready else {
                applyVariation(recommendedProductsNumber: defaultValue)
                return
            }
            let variation = try? kameleoonClient.getVariation(featureKey: "featureKey")
            let recommendedProductsNumber = variation.variables["recommendedProductsNumber"]?.value as? Int ?? defaultValue

            applyVariation(recommendedProductsNumber: recommendedProductsNumber)
        }
    }
    ```

    ##### Arguments

    | Nom                               | Type             | Description                                                                                                                                                             | Par défaut                                                                                               |
    | --------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optionnel*) | `Int`            | Timeout pour le processus d'initialisation                                                                                                                              | [`defaultTimeoutMillisecond`](#create) ou [`default_timeout_millisecond`](#configuration-supplémentaire) |
    | callback (*requis*)               | `(Bool) -> Void` | Objet callback. C'est une expression lambda qui obtiendra un argument `Bool` représentant si le `KameleoonClient` est devenu prêt avant que le timeout ne soit atteint. |                                                                                                          |
  </Tab>

  <Tab title="Swift (Async)">
    <Warning>
      Une erreur courante consiste à appeler des fonctions `async` avec `try?` ou à l'intérieur d'un bloc `do-catch` **imbriqué** **sans relancer `CancellationError`**. Cela peut interférer avec l'annulation des tâches, provoquant un comportement inattendu.
      Pour garantir une annulation correcte des tâches, évitez d'utiliser `try?` ou `do-catch` autour des fonctions `async` à moins de relancer explicitement `CancellationError`.
    </Warning>

    ```swift theme={null}
    func applyRecommendedProductsVariation() async throws {
        let defaultValue = 5 // Default control number for recommended products

        try await kameleoonClient.runWhenReady(timeoutMilliseconds: 1000)

        let variation = try kameleoonClient.getVariation(featureKey: "featureKey")
        let recommendedProductsNumber = variation.variables["recommendedProductsNumber"]?.value as? Int ?? defaultValue

        applyVariation(recommendedProductsNumber: recommendedProductsNumber)
    }
    ```

    ##### Arguments

    | Nom                               | Type  | Description                                | Par défaut                                                                                               |
    | --------------------------------- | ----- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optionnel*) | `Int` | Timeout pour le processus d'initialisation | [`defaultTimeoutMillisecond`](#create) ou [`default_timeout_millisecond`](#configuration-supplémentaire) |

    ##### Erreurs levées

    | Type                         | Description                                                             |
    | ---------------------------- | ----------------------------------------------------------------------- |
    | `KameleoonError.sdkNotReady` | Exception indiquant que le SDK n'est pas encore entièrement initialisé. |
  </Tab>
</Tabs>

### Feature flags et variations

#### isFeatureActive()

* *📨 Envoie des données de tracking à Kameleoon (selon le paramètre `track`)*

<Note>
  Cette méthode s'appelait auparavant `activateFeature`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Pour activer un feature toggle, appelez cette méthode. `isFeatureActive()` accepte `featureKey` comme argument requis pour vérifier si la fonctionnalité spécifiée sera active pour un visiteur.

Si un visiteur n'a jamais été associé à ce feature flag, cette méthode renvoie une valeur booléenne aléatoire (`true` si l'utilisateur doit voir cette fonctionnalité, sinon `false`). Si le visiteur est déjà enregistré avec ce feature flag, la méthode renvoie la valeur précédente du `featureFlag`.

Assurez-vous d'implémenter la gestion des erreurs comme indiqué dans l'exemple de code pour capturer les erreurs potentielles.

<Note>
  Kameleoon utilise le tracking pour compter les sessions et les visiteurs lorsque vous appelez certaines méthodes, telles que `isFeatureActive()`, `getVariation()` ou `getVariations()`.

  Utilisez la valeur par défaut `true` pour le paramètre `track` lorsque vous exposez des visiteurs à une variation et devez les compter. Définissez le paramètre `track` sur `false` uniquement si vous appelez ces méthodes avant d'exposer les visiteurs.

  Par exemple, si vous appelez `getVariations()` pour récupérer toutes les variations avant d'exposer les visiteurs, définissez le paramètre `track` sur `false`. Ce paramètre empêche Kameleoon de compter prématurément une session. Vous pouvez ensuite déclencher le tracking plus tard lorsque vous exposez explicitement le visiteur.

  Kameleoon envoie des données de tracking toutes les secondes par défaut. Vous pouvez configurer cet intervalle jusqu'à cinq secondes en utilisant l'option de configuration de l'intervalle de tracking. Kameleoon regroupe les événements de tracking en une seule session tant que l'intervalle entre les événements est inférieur à 30 minutes. Si plus de 30 minutes s'écoulent entre les événements de tracking, Kameleoon comptabilise les événements comme des sessions séparées. Une visite apparaît dans vos rapports 30 minutes après le dernier événement enregistré dans la session.
</Note>

```swift theme={null}
let featureKey = "new_checkout"
var hasNewCheckout = false

do {
    hasNewCheckout = try kameleoonClient.isFeatureActive(featureKey: featureKey)
    // disabling tracking
    hasNewCheckout = kameleoonClient.isFeatureActive(featureKey: featureKey, track: false);
} catch {
    switch error {
        case KameleoonError.sdkNotReady:
            // Exception indicating that the SDK has not completed its initialization yet.
            hasNewCheckout = false
        case KameleoonError.Feature.notFound:
		    // The feature key is not in the configuration file that has been fetched by the SDK.
            hasNewCheckout = false
        default:
            // Any other error.
            hasNewCheckout = false
    }
}

if hasNewCheckout
{
  // Implement new checkout code here
}
```

<Warning>
  La méthode `isFeatureActive()` évalue la variante servie, et non l'état du master flag. Si vous excluez des règles, la méthode utilise l'état par défaut **Then, for everyone else serve**. Si vous sélectionnez **Off** pour cet état par défaut, la méthode renvoie toujours `false` même lorsque le master feature flag est **On**.
</Warning>

##### Arguments

| Nom        | Type     | Description                                                                                                          |
| ---------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| featureKey | `String` | La clé de la fonctionnalité que vous souhaitez exposer à un utilisateur. Ce champ est requis.                        |
| track      | `Bool`   | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité (`true` par défaut). |

##### Valeur de retour

| Type   | Description                                               |
| ------ | --------------------------------------------------------- |
| `Bool` | Valeur de la fonctionnalité enregistrée pour le visiteur. |

##### Erreurs levées

| Type                              | Description                                                                                                                                                                                                                                                                                                     |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `KameleoonError.sdkNotReady`      | Exception indiquant que le SDK n'est pas entièrement initialisé.                                                                                                                                                                                                                                                |
| `KameleoonError.Feature.notFound` | Exception indiquant que l'ID de fonctionnalité demandé n'a pas été trouvé dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas encore été activé du côté de Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application web). |

#### getVariation()

* 📨 *Envoie des données de tracking à Kameleoon (selon le paramètre `track`)*

Récupère la [`Variation`](#variation) attribuée à un visiteur donné pour un feature flag spécifique.

Cette méthode prend un `visitorCode` et un `featureKey` comme arguments obligatoires. L'argument `track` est optionnel et vaut `true` par défaut.

Elle retourne la `Variation` attribuée au visiteur. Si le visiteur n'est associé à aucune règle de feature flag, la méthode retourne la `Variation` par défaut pour le feature flag donné.

Assurez-vous qu'une gestion appropriée des erreurs est implémentée dans votre code pour gérer les exceptions potentielles.

<Note>
  La variation par défaut fait référence à la variation attribuée à un visiteur lorsqu'il ne correspond à aucune règle de livraison prédéfinie pour un feature flag. En d'autres termes, c'est la variation de repli appliquée à tous les utilisateurs qui ne sont pas ciblés par des règles spécifiques. Elle est représentée comme la variation dans la section « Then, for everyone else... » dans une interface de gestion.
</Note>

```swift theme={null}
let featureKey = "featureKey"
var variation: Types.Variation?
do {
    variation = try kameleoonClient.getVariation(featureKey: featureKey)
    // disabling tracking
    variation = kameleoonClient.getVariation(featureKey: featureKey, track: false);
} catch {
    switch error {
        case KameleoonError.sdkNotReady:
            // Exception indicating that the SDK has not completed its initialization yet.
        case KameleoonError.Feature.notFound:
		    // The feature key is not in the configuration file that has been fetched by the SDK.
        case KameleoonError.Feature.environmentDisabled:
		    // The feature flag is disabled for the environment.
        default:
            // Any other error.
    }
}

let title = variation?.variables["title"].value

switch variation?.key {
    case "on":
        // Main variation key is selected for visitorCode
    case "alternative_variation":
        // Alternative variation key
    default:
        // Default variation key
}
```

##### Arguments

| Nom                    | Type     | Description                                                                                      | Par défaut |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------ | ---------- |
| visitorCode (*requis*) | `String` | Identifiant unique du visiteur.                                                                  |            |
| featureKey (*requis*)  | `String` | Clé de la fonctionnalité que vous souhaitez exposer à un visiteur.                               |            |
| track (*optionnel*)    | `Bool`   | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité. | `true`     |

##### Valeur de retour

| Type        | Description                                                                                  |
| ----------- | -------------------------------------------------------------------------------------------- |
| `Variation` | Une [`Variation`](#variation) attribuée à un visiteur donné pour un feature flag spécifique. |

##### Erreurs levées

| Type                                         | Description                                                                                                                                                                                                                                                                               |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `KameleoonError.visitorCodeInvalid`          | Exception indiquant que le visitor code fourni n'est pas valide. Il est soit vide, soit plus long que 255 caractères.                                                                                                                                                                     |
| `KameleoonError.Feature.notFound`            | Exception indiquant que la feature key demandée n'a pas été trouvée dans la configuration interne du SDK. Cela signifie généralement que le feature flag n'est pas activé dans l'application Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application). |
| `KameleoonError.Feature.environmentDisabled` | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                                                                                          |

#### getVariations()

* 📨 *Envoie des données de tracking à Kameleoon (selon le paramètre `track`)*

Récupère un map d'objets [`Variation`](#variation) attribués à un visiteur donné pour tous les feature flags.

Cette méthode itère sur tous les feature flags disponibles et renvoie la `Variation` attribuée pour chaque flag associé au visiteur spécifié. Elle prend `onlyActive` et `track` comme arguments optionnels.

* Si `onlyActive` est défini sur `true`, la méthode `getVariations()` renverra les variations de feature flag à condition que l'utilisateur ne soit pas attribué à la variation `off`.
* Le paramètre `track` contrôle si la méthode va suivre ou non les attributions de variation. Par défaut, il est défini sur `true`. S'il est défini sur `false`, le tracking sera désactivé.

Le map renvoyé se compose de clés de feature flag comme clés et de leurs `Variation` correspondantes comme valeurs. Si aucune variation n'est attribuée pour un feature flag, la méthode renvoie la `Variation` par défaut pour ce flag.

Une gestion appropriée des erreurs doit être implémentée pour gérer les exceptions potentielles.

<Note>
  La variation par défaut fait référence à la variation attribuée à un visiteur lorsqu'il ne correspond à aucune règle de livraison prédéfinie pour un feature flag. En d'autres termes, c'est la variation de repli appliquée à tous les utilisateurs qui ne sont pas ciblés par des règles spécifiques. Elle est représentée comme la variation dans la section « Then, for everyone else... » dans une interface de gestion.
</Note>

```swift theme={null}
do {
    let variations = kameleoonClient.getVariations();
    // only active variations
    let variations = kameleoonClient.getVariations(onlyActive: true);
    // disable tracking
    let variations = kameleoonClient.getVariations(track: false);
} catch KameleoonError.sdkNotReady {
    // Exception indicating that the SDK has not completed its initialization yet.
}
```

##### Arguments

| Nom                      | Type   | Description                                                                                                                  | Par défaut |
| ------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------- | ---------- |
| onlyActive (*optionnel*) | `Bool` | Un paramètre optionnel indiquant s'il faut renvoyer les variations pour les feature flags actifs (`true`) ou tous (`false`). | `false`    |
| track (*optionnel*)      | `Bool` | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité.                             | `true`     |

##### Valeur de retour

| Type                      | Description                                                                                                                               |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `Dict<String, Variation>` | Map contenant les objets [`Variation`](#variation) attribués aux feature flags en utilisant les clés des fonctionnalités correspondantes. |

##### Erreurs levées

| Type                         | Description                                                 |
| ---------------------------- | ----------------------------------------------------------- |
| `KameleoonError.sdkNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

#### setForcedVariation()

Cette méthode vous permet d'attribuer par programmation une [`Variation`](#variation) spécifique à un utilisateur, en contournant le processus d'évaluation standard. Cela est particulièrement utile pour les expériences contrôlées où la logique d'évaluation habituelle n'est pas requise ou doit être ignorée. Cela peut également être utile dans des scénarios comme le débogage ou les tests personnalisés.

Lorsqu'une variation **forcée** est définie, elle remplace la logique d'évaluation en temps réel de Kameleoon. Les processus tels que la segmentation, les conditions de ciblage et les calculs algorithmiques sont ignorés. Pour préserver la segmentation et les conditions de ciblage pendant une expérience, définissez plutôt `forceTargeting=false`.

Une variation forcée est traitée de la même manière qu'une variation évaluée. Elle est suivie dans les analyses et stockée dans le contexte utilisateur comme toute variation évaluée standard, assurant la cohérence dans le reporting.

La méthode peut lever des exceptions dans certaines conditions (par exemple, paramètres invalides, contexte utilisateur ou problèmes internes). Une gestion appropriée des exceptions est essentielle pour garantir que votre application reste stable et résiliente.

```swift theme={null}
let experimentId = 9516
do {
    // Forcing the variation "on" for the experiment 9516 for the visitor
    try kameleoonClient.setForcedVariation(experimentId: experimentId, variationKey: "on")

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

    // Resetting the forced variation for the experiment 9516 for the visitor
    try kameleoonClient.setForcedVariation(experimentId: experimentId, variationKey: nil);
} catch {
    // Handling the KameleoonError, KameleoonError.Feature and common Error
}
```

##### Arguments

| Nom                          | Type     | Description                                                                                                                                                                     | Par défaut |
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| experimentId (*requis*)      | `Int`    | **Experiment Id** qui sera ciblé et sélectionné pendant le processus d'évaluation.                                                                                              |            |
| variationKey (*requis*)      | `String` | **Variation Key** correspondant à une `Variation` qui doit être forcée comme valeur renvoyée pour l'expérience. Si la valeur est `nil`, la variation forcée sera réinitialisée. |            |
| forceTargeting (*optionnel*) | `Bool`   | Indique si le ciblage de l'expérience doit être forcé et ignoré (`true`) ou appliqué comme dans le processus d'évaluation standard (`false`).                                   | `true`     |

##### Erreurs levées

| Type                                        | Description                                                                                                                                                                                                                                            |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `KameleoonError.sdkNotReady`                | Indique que le SDK n'est pas encore entièrement initialisé.                                                                                                                                                                                            |
| `KameleoonError.Feature.experimentNotFound` | Exception indiquant que l'experiment id demandé n'a pas été trouvé dans la configuration interne du SDK. C'est généralement normal et signifie que l'expérience correspondante de la règle n'a pas encore été activée du côté de Kameleoon.            |
| `KameleoonError.Feature.variationNotFound`  | Exception indiquant que la variation key(id) demandée n'a pas été trouvée dans la configuration interne du SDK. C'est généralement normal et signifie que l'expérience correspondante de la variation n'a pas encore été activée du côté de Kameleoon. |

<Info>
  Dans la plupart des cas, seule l'erreur de base, `KameleoonError/KameleoonError.Feature`, doit être gérée, comme démontré dans l'exemple. Cependant, si différents types d'erreurs nécessitent une réponse, gérez chacune séparément en fonction des exigences spécifiques. De plus, pour une fiabilité accrue, les erreurs générales du langage peuvent être gérées en incluant `Error`.
</Info>

#### evaluateAudiences()

* 📨 *Envoie des données de tracking à Kameleoon*

Cette méthode évalue les visiteurs par rapport à tous les segments disponibles dans Audiences Explorer et suit ceux qui correspondent.

`evaluateAudiences()` doit être appelée **après que toutes les données pertinentes du visiteur ont été définies ou mises à jour**, et **juste avant** d'obtenir une variation de fonctionnalité ou de vérifier un feature flag. Cette approche garantit que le visiteur est évalué par rapport aux données les plus récentes disponibles, permettant une attribution d'audience précise basée sur tous les critères.

Après avoir appelé cette méthode, vous pouvez effectuer une analyse détaillée des performances des segments dans Audiences Explorer.

```swift theme={null}
do {
    try kameleoonClient.evaluateAudiences();
} catch {
    // Handling the errors
}
```

##### Erreurs levées

| Type                         | Description                                                 |
| ---------------------------- | ----------------------------------------------------------- |
| `KameleoonError.sdkNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

<Info>
  Dans la plupart des cas, seule l'erreur de base, `KameleoonError/KameleoonError.Feature`, doit être gérée, comme démontré dans l'exemple. Cependant, si différents types d'erreurs nécessitent une réponse, gérez chacune séparément en fonction des exigences spécifiques. De plus, pour une fiabilité accrue, les erreurs générales du langage peuvent être gérées en incluant `Error`.
</Info>

#### getFeatureList()

<Tip>
  Si vous souhaitez itérer sur tous les feature flags et appeler [`getVariation()`](#getvariation) sur chacun, utilisez plutôt la méthode [`getVariations()`](#getvariations).
</Tip>

Renvoie une liste de clés de feature flag actuellement disponibles pour le SDK.

```swift theme={null}
let allFeatureList = kameleoonClient.getFeatureList()
```

##### Valeur de retour

| Type       | Description                   |
| ---------- | ----------------------------- |
| `[String]` | Liste de clés de feature flag |

#### getDataFile()

<Tip>
  Pour évaluer tous les feature flags, utilisez [`getVariations()`](#getvariations). Cette méthode est plus efficace que d'appeler `DataFile` et de parcourir les flags avec [`getVariation()`](#getvariation).
</Tip>

Renvoie la configuration actuelle du SDK sous la forme d'un objet [`DataFile`](#datafile).

```swift theme={null}
do {
    let dataFile = try kameleoonClient.getDataFile()
} catch KameleoonError.sdkNotReady {
    // Exception indicates that the SDK has not completed its initialization yet.
} catch {
    // Handling the KameleoonError, KameleoonError.Feature and common Error
}
```

##### Valeur de retour

| Type       | Description                                                  |
| ---------- | ------------------------------------------------------------ |
| `DataFile` | Le [`DataFile`](#datafile) contenant la configuration du SDK |

##### Erreurs levées

| Type                         | Description                                                 |
| ---------------------------- | ----------------------------------------------------------- |
| `KameleoonError.sdkNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

### Objectifs

#### trackConversion()

* 📨 *Envoie des données de tracking à Kameleoon*

Utilisez cette méthode pour suivre les conversions. Cette méthode nécessite `goalId` pour suivre la conversion sur cet [objectif](/user-manual//assets/goals/create-a-goal) particulier. De plus, cette méthode accepte également les arguments `revenue`, `metadata` et `negative`.

La méthode `trackConversion()` ne renvoie aucune valeur. Cette méthode est non bloquante car l'appel serveur est effectué de manière asynchrone.

```swift theme={null}
let goalId = 83023
kameleoonClient.trackConversion(goalId: goalId, revenue: 10.0)

kameleoonClient.trackConversion(goalId: goalId, revenue: 10.0, metadata: CustomData(id: 1, values: "metadata"))
```

##### Arguments

| Nom                    | Type                           | Description                                                                                                                                              | Par défaut |
| ---------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| goalId (*requis*)      | `Int`                          | ID de l'objectif.                                                                                                                                        |            |
| revenue (*optionnel*)  | `Double`                       | Revenu de la conversion.                                                                                                                                 | `0`        |
| negative (*optionnel*) | `Bool`                         | Définit si le revenu est positif ou négatif.                                                                                                             | `false`    |
| metadata (*optionnel*) | `CustomData... / [CustomData]` | Métadonnées de la conversion. [Doivent être définies au préalable dans l'application Kameleoon](/fr/user-manual/assets/goals/create-a-goal#métadonnées). | `[]`       |

<Note>
  Les valeurs des métadonnées sont accessibles via les [exports de données brutes](/user-manual/experiment-analytics/analyze-results/results-page/results-page-actions#Export) et [la page de résultats](/user-manual/experiment-analytics/analyze-results/data-and-metrics/goal-metadata).

  Si le paramètre `metadata` est fourni, Kameleoon utilisera ces valeurs spécifiées pour la conversion actuelle au lieu de ce qui a été précédemment collecté avec la méthode [`addData()`](#adddata). Si le paramètre est omis, Kameleoon utilisera les dernières valeurs suivies pour ces [`CustomData`](#customdata) avant la conversion et au sein de la même visite.

  Kameleoon ne prendra en compte que les valeurs de métadonnées explicitement passées en tant que paramètres à la méthode `trackConversion()`.

  Dans l'exemple ci-dessous, Kameleoon associera la conversion uniquement à la valeur de custom data explicitement fournie en tant que paramètre (ici : index 5 avec la valeur « Amex Credit Card »).

  ```swift theme={null}
  kameleoonClient.addData([CustomData(id: 5, values: "Credit Card"), CustomData(id: 9, "Express Delivery")]);
  kameleoonClient.trackConversionWithOptParams(goalId: 1000, metadata: CustomData(5, "Amex Credit Card"));
  ```
</Note>

### Événements

#### updateConfigurationHandler()

La méthode `updateConfigurationHandler()` vous permet de gérer l'événement lorsque la configuration a des données mises à jour. Elle prend un paramètre d'entrée, **handler**. Le handler qui sera appelé lorsque la configuration est mise à jour à l'aide d'un événement de configuration en temps réel.

<Note>
  Ce handler n'est déclenché que lorsque le SDK fonctionne en [mode streaming](/developer-docs/feature-experimentation/technical-reference/technical-considerations#streaming-option-premium) (server-sent events). Il **n'est pas** appelé pour les actualisations de configuration effectuées en mode polling par défaut (`refreshIntervalMinute`).
</Note>

```swift theme={null}
kameleoonClient.updateConfigurationHandler {
  // configuration was updated
}
```

##### Arguments

| Nom     | Type                     | Description                                                                                                                 |
| ------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| handler | `Optional<(() -> Void)>` | Le handler qui sera appelé lorsque la configuration est mise à jour à l'aide d'un événement de configuration en temps réel. |

### Données visiteur

#### visitorCode

Renvoie le visitor code unique utilisé dans le SDK.

```swift theme={null}
let visitorCode = kameleoonClient.visitorCode
```

##### Valeur de retour

| Type     | Description                                                     |
| -------- | --------------------------------------------------------------- |
| `String` | Chaîne représentant un visitor code unique utilisé dans le SDK. |

#### addData()

La méthode `addData()` ajoute des [données de ciblage](#types-de-données) au stockage afin que d'autres méthodes puissent utiliser ces données pour décider de cibler ou non le visiteur actuel.

La méthode `addData()` ne renvoie aucune valeur et n'interagit pas par elle-même avec les serveurs backend de Kameleoon. Au lieu de cela, toutes les données déclarées sont enregistrées pour une transmission future à l'aide de la méthode [`flush()`](#flush). Cette approche réduit le nombre d'appels serveur effectués, car les données sont généralement regroupées en un seul appel serveur déclenché par le `flush()`.

La méthode [`trackConversion()`](#trackconversion) envoie également toutes les données précédemment associées, tout comme `flush()`. Il en va de même pour les méthodes [`getVariation()`](#getvariation) et [`getVariations()`](#getvariations) si une règle d'expérimentation est déclenchée.

<Tip>
  Chaque visiteur ne peut avoir qu'une seule instance de données associées pour la plupart des types de données. Cependant, [`CustomData`](#customdata) est une exception. Les visiteurs peuvent avoir une instance de `CustomData` associée par index.
</Tip>

```swift theme={null}
// Add a single data item (tracked by default)
kameleoonClient.addData(CustomData(index: 1, values: "value"))

// Add multiple data items (tracked by default)
kameleoonClient.addData(
    CustomData(index: 20, values: "value"),
    Geolocation(country: "France")
)

// Add multiple data items stored locally for targeting only (not sent to the Kameleoon Data API)
kameleoonClient.addData(
    track: false,
    CustomData(index: 20, values: "value"),
    Geolocation(country: "France")
)
```

##### Arguments

| Nom                 | Type                                 | Description                                                                                                                                                                                                                                    | Valeur par défaut |
| ------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| track (*optionnel*) | `Bool`                               | Spécifie si les données ajoutées sont éligibles au tracking. Lorsqu'il est défini sur `false`, les données sont stockées localement et utilisées uniquement pour l'évaluation du ciblage ; elles ne sont pas envoyées à la Kameleoon Data API. | `true`            |
| data (*requis*)     | `KameleoonData... / [KameleoonData]` | Collection de types de données Kameleoon.                                                                                                                                                                                                      |                   |

#### flush()

* 📨 *Envoie des données de tracking à Kameleoon*

La méthode `flush()` collecte les données Kameleoon liées au visiteur. Elle envoie ensuite une requête de tracking, ainsi que toutes les données ajoutées avec la méthode `addData` qui n'ont pas encore été envoyées en utilisant l'une de [ces méthodes](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics). `flush()` est non bloquant car l'appel serveur est effectué de manière asynchrone.

`flush` fournit un contrôle sur le moment où les données associées à un `visitorCode` donné sont envoyées aux serveurs. Par exemple, si `addData()` est appelé une douzaine de fois, envoyer des données au serveur à chaque invocation de `addData()` serait inefficace. Appelez `flush()` une seule fois.

```swift theme={null}
kameleoonClient.addData(CustomData(id: 20, values: "true", "20"))
kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))

kameleoonClient.flush() // Interval tracking (most performant way for tracking)
kameleoonClient.flush(instant: true) // Instant tracking
```

##### Arguments

| Nom     | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| instant | `Bool` | Indicateur booléen indiquant si les données doivent être envoyées instantanément (`true`) ou selon l'intervalle de tracking par défaut (`false`) défini avec le paramètre du SDK `trackingIntervalMillisecond` dans [`KameleoonClientConfig`](/developer-docs/sdks/mobile-sdks/ios-sdk#initialize-the-kameleoon-client) ou [`tracking_interval_millisecond`](#configuration-supplémentaire). Ce champ est optionnel. |

##### Erreurs levées

| Type                         | Description                                                     |
| ---------------------------- | --------------------------------------------------------------- |
| `KameleoonError.sdkNotReady` | Erreur indiquant que le SDK n'a pas terminé son initialisation. |

#### getRemoteData()

* 🔄 *Effectue une requête asynchrone*

<Note>
  Cette méthode s'appelait auparavant `retrieveDataFromRemoteSource`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Utilisez cette méthode pour récupérer des données à partir d'un serveur Kameleoon distant en fonction du `siteCode` actif et de l'argument `key` (ou du `visitorCode` actif si la `key` est omise). Le `visitorCode` et le `siteCode` sont spécifiés dans `KameleoonClientFactory.create()`. Les données peuvent être stockées rapidement et facilement sur des serveurs distants hautement évolutifs en utilisant la Kameleoon Data API. L'application peut ensuite récupérer les données à l'aide de cette méthode.

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` en tant qu'argument à la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées avec succès.
  * Utiliser des opérations asynchrones.
</Warning>

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    struct Test1: Decodable {
      let value: String

      private enum CodingKeys: String, CodingKey {
        case value = "json_value"
      }
    }

    kameleoonClient.getRemoteData(key: "test") { (result: Result<Test1, Error>) in
        switch result {
            case .success(let test1):
                // test1 is a decoded value for Test1 type
            case .failure:
                // error includes informaion about request's failure
        }
    }

    kameleoonClient.getRemoteData(key: "test") { (data: Result<Data, Error>) in
        switch result {
            case .success(let data):
                if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
                    print(json)
                }
            case .failure:
                // error includes informaion about request's failure
        }
    }
    ```

    ##### Arguments

    | Nom                   | Type                                    | Description                                                              | Par défaut |
    | --------------------- | --------------------------------------- | ------------------------------------------------------------------------ | ---------- |
    | key (*optionnel*)     | `String`                                | La clé à laquelle sont associées les données que vous souhaitez obtenir. | `""`       |
    | completion (*requis*) | `(Result<T: Decodable, Error>) -> Void` | Le callback qui traite les données reçues.                               |            |
  </Tab>

  <Tab title="Swift (Async)">
    <Warning>
      Une erreur courante consiste à appeler des fonctions `async` avec `try?` ou à l'intérieur d'un bloc `do-catch` **imbriqué** **sans relancer `CancellationError`**. Cela peut interférer avec l'annulation des tâches, provoquant un comportement inattendu.
      Pour garantir une annulation correcte des tâches, évitez d'utiliser `try?` ou `do-catch` autour des fonctions `async` à moins de relancer explicitement `CancellationError`.
    </Warning>

    ```swift theme={null}
    struct Test1: Decodable {
      let value: String

      private enum CodingKeys: String, CodingKey {
        case value = "json_value"
      }
    }

    Task {
        do {
            let test1: Test1 = try await kameleoonClient.getRemoteData(key: "test")
            // test1 is a decoded value for Test1 type
        } catch {
            // handle error
        }
    }

    Task {
        do {
            let data: Data = try await kameleoonClient.getRawRemoteData(key: "test")
            if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
                print(json)
            }
        } catch {
            // handle error
        }
    }
    ```

    ##### Arguments

    | Nom               | Type     | Description                                                              | Par défaut |
    | ----------------- | -------- | ------------------------------------------------------------------------ | ---------- |
    | key (*optionnel*) | `String` | La clé à laquelle sont associées les données que vous souhaitez obtenir. | `""`       |

    ##### Valeur de retour

    | Type        | Description                                                                                                                  |
    | ----------- | ---------------------------------------------------------------------------------------------------------------------------- |
    | `Decodable` | Un objet [`Decodable`](https://developer.apple.com/documentation/swift/decodable) contenant la valeur récupérée et analysée. |

    ##### Erreurs levées

    | Type    | Description                                             |
    | ------- | ------------------------------------------------------- |
    | `Error` | Indique que la requête a échoué en raison d'une erreur. |
  </Tab>
</Tabs>

#### getRemoteVisitorData()

* 🔄 *Effectue une requête asynchrone*

`getRemoteVisitorData()` est une méthode asynchrone permettant de récupérer les Kameleoon Visits Data du visiteur depuis la Kameleoon Data API. La méthode ajoute les données au stockage pour que d'autres méthodes les utilisent lors de la prise de décisions de ciblage.

Les données obtenues à l'aide de cette méthode jouent un rôle important lorsque vous souhaitez :

* utiliser les données collectées sur d'autres appareils.
* accéder à l'historique d'un utilisateur, comme les custom data collectées lors de visites précédentes.

Lisez [cet article](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation) pour une meilleure compréhension des cas d'usage possibles.

<Note>
  Par défaut, `getRemoteVisitorData()` récupère automatiquement les dernières custom data stockées avec `scope=Visitor` et les attache au visiteur sans qu'il soit nécessaire d'appeler la méthode `addData()`. C'est particulièrement utile pour [synchroniser les custom data entre plusieurs appareils](/developer-docs/sdks/web-sdks/nodejs-sdk#synchronizing-custom-data-across-devices).

  Il est recommandé de vérifier uniquement les résultats échoués. Cependant, si nécessaire, vous pouvez vérifier que les données ont été ajoutées au visiteur et sont disponibles à des fins de ciblage (ou pour le débogage, bien que l'utilisation du [logging](#logging) soit préférable pour le débogage). De plus, les données peuvent être gérées manuellement si le paramètre `addData=false` est passé.
</Note>

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` en tant qu'argument à la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées avec succès et ajoutées au visiteur.
  * Utiliser des opérations asynchrones.
</Warning>

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    // Fetch visitor data and automatically add it
    kameleoonClient.getRemoteVisitorData { result in
        switch result {
            case .success(let visitorData):
                // visitorData includes all retrieved data that was added for the visitor
            case .failure:
                // Handle the error, which contains information about the request failure
        }
    }

    // Fetch visitor data without automatically adding it
    kameleoonClient.getRemoteVisitorData(addData: false) { result in
        switch result {
            case .success(let visitorData):
                // visitorData includes all retrieved data that was added for the visitor
            case .failure:
                // Handle the error, which contains information about the request failure
        }
    }

    // Fetch a custom list of data types
    let filter = Types.RemoteVisitorDataFilter(
        previousVisitAmount: 25, currentVisit: true, conversions: true, experiments: true, geolocation: true
    )
    kameleoonClient.getRemoteVisitorData(filter: filter) { result in
        switch result {
            case .success(let visitorData):
                // visitorData includes all retrieved data that was added for the visitor
            case .failure:
                // Handle the error, which contains information about the request failure
        }
    }
    ```

    ##### Arguments

    | Nom                   | Type                                       | Description                                                                                                                                                                                           | Par défaut                        |
    | --------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
    | filter (*optionnel*)  | `RemoteVisitorDataFilter`                  | Filtre qui sélectionne quelles données doivent être récupérées depuis l'historique de visite. Par défaut, la méthode récupère `CustomData` de la visite actuelle et de la dernière visite précédente. | `RemoteVisitorDataFilter.default` |
    | addData (*optionnel*) | `Boolean`                                  | Un booléen indiquant si la méthode doit automatiquement ajouter les données récupérées pour un visiteur.                                                                                              | `true`                            |
    | completion (*requis*) | `(Result<[KameleoonData], Error>) -> Void` | Le callback qui traite les données visiteur reçues.                                                                                                                                                   |                                   |
  </Tab>

  <Tab title="Swift (Async)">
    <Warning>
      Une erreur courante consiste à appeler des fonctions `async` avec `try?` ou à l'intérieur d'un bloc `do-catch` **imbriqué** **sans relancer `CancellationError`**. Cela peut interférer avec l'annulation des tâches, provoquant un comportement inattendu.
      Pour garantir une annulation correcte des tâches, évitez d'utiliser `try?` ou `do-catch` autour des fonctions `async` à moins de relancer explicitement `CancellationError`.
    </Warning>

    ```swift theme={null}
    // Fetch visitor data and automatically add it
    Task {
        do {
            let visitorData = try await kameleoonClient.getRemoteVisitorData()
            // visitorData includes all retrieved data that was added for the visitor
        } catch {
            // Handle the error, which contains information about the request failure
        }
    }

    // Fetch visitor data without automatically adding it
    Task {
        do {
            let visitorData = try await kameleoonClient.getRemoteVisitorData(addData: false)
            // visitorData includes all retrieved data but was not added for the visitor
        } catch {
            // Handle the error, which contains information about the request failure
        }
    }

    // Fetch a custom list of data types
    Task {
        do {
            let filter = Types.RemoteVisitorDataFilter(
                previousVisitAmount: 25, currentVisit: true, conversions: true, experiments: true, geolocation: true
            )
            let visitorData = try await kameleoonClient.getRemoteVisitorData(filter: filter)
            // visitorData includes all retrieved data based on the specified filter
        } catch {
            // Handle the error, which contains information about the request failure
        }
    }
    ```

    ##### Arguments

    | Nom                   | Type                      | Description                                                                                                                                                                                           | Par défaut                        |
    | --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
    | filter (*optionnel*)  | `RemoteVisitorDataFilter` | Filtre qui sélectionne quelles données doivent être récupérées depuis l'historique de visite. Par défaut, la méthode récupère `CustomData` de la visite actuelle et de la dernière visite précédente. | `RemoteVisitorDataFilter.default` |
    | addData (*optionnel*) | `Boolean`                 | Un booléen indiquant si la méthode doit automatiquement ajouter les données récupérées pour un visiteur.                                                                                              | `true`                            |

    ##### Valeur de retour

    | Type              | Description                                                   |
    | ----------------- | ------------------------------------------------------------- |
    | `[KameleoonData]` | Un tableau contenant les données récupérées pour le visiteur. |

    ##### Erreurs levées

    | Type    | Description                                             |
    | ------- | ------------------------------------------------------- |
    | `Error` | Indique que la requête a échoué en raison d'une erreur. |
  </Tab>
</Tabs>

##### Utilisation des paramètres avec RemoteVisitorDataFilter

La méthode `getRemoteVisitorData()` offre une flexibilité en vous permettant de définir divers paramètres lors de la récupération des données sur les visiteurs. Que vous cibliez en fonction d'objectifs, d'expériences ou de variations, la même approche s'applique à tous les types de données.

Par exemple, supposons que vous souhaitiez récupérer des données sur les visiteurs qui ont atteint un objectif « Order transaction ». Vous pouvez spécifier des paramètres dans la méthode `getRemoteVisitorData()` pour affiner votre ciblage. Par exemple, si vous souhaitez cibler uniquement les utilisateurs qui ont converti sur l'objectif lors de leurs cinq dernières visites, vous pouvez définir le paramètre `previousVisitAmount` sur `5` et `conversions` sur `true`.

La flexibilité présentée dans cet exemple ne se limite pas aux données d'objectif. Vous pouvez utiliser les paramètres de la méthode `getRemoteVisitorData()` pour récupérer des données sur divers comportements des visiteurs.

<Note>
  Voici la liste des options `Types.RemoteVisitorDataFilter` disponibles :

  | Nom                               | Type   | Description                                                                                                                                                                                                                                                                                                                                                                   | Par défaut |
  | --------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
  | previousVisitAmount (*optionnel*) | `Int`  | Nombre de visites précédentes à partir desquelles récupérer les données. Nombre entre `1` et `25`                                                                                                                                                                                                                                                                             | `1`        |
  | currentVisit (*optionnel*)        | `Bool` | Si true, les données de la visite actuelle seront récupérées                                                                                                                                                                                                                                                                                                                  | `true`     |
  | customData (*optionnel*)          | `Bool` | Si true, les custom data seront récupérées.                                                                                                                                                                                                                                                                                                                                   | `true`     |
  | conversions (*optionnel*)         | `Bool` | Si true, les données de conversion seront récupérées.                                                                                                                                                                                                                                                                                                                         | `false`    |
  | experiments (*optionnel*)         | `Bool` | Si true, les données d'expérience seront récupérées.                                                                                                                                                                                                                                                                                                                          | `false`    |
  | geolocation (*optionnel*)         | `Bool` | Si true, les données de géolocalisation seront récupérées.                                                                                                                                                                                                                                                                                                                    | `false`    |
  | kcs (*optionnel*)                 | `Bool` | Si true, le Kameleoon Conversion Score (KCS) sera récupéré. Nécessite le [module complémentaire AI Predictive Targeting](/user-manual/ai-predictive-targeting/target-users-based-on-likelihood-to-convert)                                                                                                                                                                    | `false`    |
  | visitorCode (*optionnel*)         | `Bool` | Si true, Kameleoon récupérera le `visitorCode` de la visite la plus récente et l'utilisera pour la visite actuelle. Le `visitorCode` est nécessaire si vous souhaitez vous assurer que le visiteur, identifié par son `visitorCode`, reçoit toujours la même variation entre les visites pour l'[expérimentation cross-device](/developer-docs/cross-device-experimentation). | `true`     |
  | personalization (*optionnel*)     | `Bool` | Si true, les données de personnalisation seront récupérées. `personalization` est requis pour la condition de personnalisation                                                                                                                                                                                                                                                | `false`    |
  | cbs (*optionnel*)                 | `Bool` | Si true, les données de score Contextual Bandit seront récupérées.                                                                                                                                                                                                                                                                                                            | `false`    |
</Note>

#### getVisitorWarehouseAudience()

* 🔄 *Effectue une requête asynchrone*

Récupère toutes les données d'audience associées au visiteur dans votre data warehouse. Le paramètre optionnel `warehouseKey` est généralement votre ID utilisateur interne. Le paramètre `customDataIndex` correspond à la custom data Kameleoon que Kameleoon utilise pour cibler vos visiteurs. Vous pouvez vous référer à la [documentation sur le ciblage warehouse](/user-manual/integrations/data-warehouses/bigquery/use-bigquery-as-a-source-audience-targeting) pour plus de détails.

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` en tant qu'argument à la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées avec succès et ajoutées au visiteur.
  * Utiliser les coroutines pour la gestion asynchrone.

  Il est recommandé de vérifier uniquement les résultats échoués. Cependant, si nécessaire, vous pouvez vérifier que les données ont été ajoutées au visiteur et sont disponibles à des fins de ciblage (ou pour le débogage, bien que l'utilisation du [logging](#logging) soit préférable pour le débogage).
</Warning>

<Tabs defaultTabIndex={0}>
  <Tab title="Swift">
    ```swift theme={null}
    // Fetch visitor warehouse audience data
    kameleoonClient.getVisitorWarehouseAudience(customDataIndex: 10) { result in
        switch result {
            case .success(let customData):
                // Data was added. You can access it from `customData`
            case .failure:
                // Handle the error, which contains information about the request failure
        }
    }

    // Fetch visitor warehouse audience data with a specific warehouse key
    kameleoonClient.getVisitorWarehouseAudience(
        warehouseKey: "warehouseKey", customDataIndex: 10
    ) { result in
        switch result {
            case .success(let customData):
                // Data was added. You can access it from `customData`
            case .failure:
                // Handle the error, which contains information about the request failure
        }
    }
    ```

    ##### Arguments

    | Nom                        | Type                                  | Description                                                                                                      | Par défaut |
    | -------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------- |
    | warehouseKey (*optionnel*) | `String`                              | La clé unique pour identifier les données du warehouse (généralement votre ID utilisateur interne).              | `""`       |
    | customDataIndex (*requis*) | `Int`                                 | Un entier représentant l'index de la custom data que vous souhaitez utiliser pour cibler vos BigQuery Audiences. |            |
    | completion                 | `(Result<CustomData, Error>) -> Void` | Le callback qui traite les données reçues.                                                                       |            |
  </Tab>

  <Tab title="Swift (Async)">
    <Warning>
      Une erreur courante consiste à appeler des fonctions `async` avec `try?` ou à l'intérieur d'un bloc `do-catch` **imbriqué** **sans relancer `CancellationError`**. Cela peut interférer avec l'annulation des tâches, provoquant un comportement inattendu.
      Pour garantir une annulation correcte des tâches, évitez d'utiliser `try?` ou `do-catch` autour des fonctions `async` à moins de relancer explicitement `CancellationError`.
    </Warning>

    ```swift theme={null}
    // Fetch visitor warehouse audience data
    Task {
        do {
            let customData = try await kameleoonClient.getVisitorWarehouseAudience(customDataIndex: 10)
            // Data was added. You can access it from `customData`
        } catch {
            // Handle the error, which contains information about the request failure
        }
    }

    // Fetch visitor warehouse audience data with a specific warehouse key
    Task {
        do {
            let customData = try await kameleoonClient.getVisitorWarehouseAudience(
                warehouseKey: "warehouseKey", customDataIndex: 10
            )
            // Data was added. You can access it from `customData`
        } catch {
            // Handle the error, which contains information about the request failure
        }
    }
    ```

    ##### Arguments

    | Nom                        | Type     | Description                                                                                                      | Par défaut |
    | -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- | ---------- |
    | warehouseKey (*optionnel*) | `String` | La clé unique pour identifier les données du warehouse (généralement votre ID utilisateur interne).              | `""`       |
    | customDataIndex (*requis*) | `Int`    | Un entier représentant l'index de la custom data que vous souhaitez utiliser pour cibler vos BigQuery Audiences. |            |

    ##### Valeur de retour

    | Type         | Description                                                                                                                                                    |
    | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `CustomData` | Une entrée [`CustomData`](#customdata) ajoutée pour un visiteur. Généralement, vous pouvez ignorer cette valeur, mais elle peut être utile à des fins de test. |

    ##### Erreurs levées

    | Type    | Description                                             |
    | ------- | ------------------------------------------------------- |
    | `Error` | Indique que la requête a échoué en raison d'une erreur. |
  </Tab>
</Tabs>

#### setLegalConsent()

Vous devez utiliser cette méthode pour spécifier si le visiteur a donné son consentement légal à l'utilisation de ses données personnelles. Définir le paramètre `legalConsent` sur `false` limite les types de données que vous pouvez inclure dans les requêtes de tracking. Cette méthode vous aide à respecter les exigences légales et réglementaires tout en gérant de manière responsable les données du visiteur. Vous trouverez plus d'informations sur les données personnelles dans la [politique de gestion du consentement](/user-manual/project-management/consent-management-policy).

##### Arguments

| Nom          | Type    | Description                                                                                                                                                                                                                                     |
| ------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| legalConsent | boolean | Une valeur booléenne représentant le statut du consentement légal. `true` indique que le visiteur a donné son consentement légal ; `false` indique que le visiteur n'a jamais fourni, ou a retiré, son consentement légal. Ce champ est requis. |

```swift theme={null}
kameleoonClient.setLegalConsent(true)
```

### Types de données

Cette section liste les types de données pris en charge par Kameleoon. Plusieurs types de données standard sont fournis, ainsi que le type `CustomData` pour définir des types de données personnalisés.

#### Conversion

L'ensemble de données `Conversion` stocké ici peut être utilisé pour filtrer les rapports d'expérience et de personnalisation par tout objectif qui lui est associé.

<Tip>
  * Chaque visiteur peut avoir plusieurs objets `Conversion`.
  * Vous pouvez trouver le `goalId` dans l'application Kameleoon.
</Tip>

| Nom                    | Type                           | Description                                  | Par défaut |
| ---------------------- | ------------------------------ | -------------------------------------------- | ---------- |
| goalId (*requis*)      | `Int`                          | ID de l'objectif.                            |            |
| revenue (*optionnel*)  | `Double`                       | Revenu de la conversion                      | `0`        |
| negative (*optionnel*) | `Bool`                         | Définit si le revenu est positif ou négatif. | `false`    |
| metadata (*optionnel*) | `CustomData... / [CustomData]` | Métadonnées de la conversion.                | `[]`       |

```swift theme={null}
kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))

kameleoonClient.addData(Conversion(goalId: 32, metadata: CustomData(id: 1, values: "metadata")))
```

#### CustomData

`CustomData` permet d'associer facilement n'importe quel type de données à chaque visiteur. `CustomData` peut ensuite être utilisé comme condition de ciblage dans les [segments](/user-manual/assets/segments/create-a-segment/) ou comme filtre/décomposition dans les rapports d'expérience.

Pour en savoir plus sur les custom data, veuillez consulter cet [article](/developer-docs/custom-data).

| Nom                     | Type                      | Description                                                                                                                                                                                                                             |        |
| ----------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| index/name (*requis*)   | `Int`/`String`            | Index ou Nom des custom data. **Soit `index`, soit `name` doit être fourni** pour identifier les données.                                                                                                                               |        |
| overwrite (*optionnel*) | `Bool`                    | Indicateur permettant de contrôler explicitement comment les valeurs sont stockées et comment elles apparaissent dans les rapports. [Voir plus](/developer-docs/custom-data#default-logic-when-overwrite-parameter-is-false-or-omitted) | `true` |
| values (*requis*)       | `String...` ou `[String]` | Valeurs des custom data à stocker.                                                                                                                                                                                                      |        |

<Note>
  * Chaque visiteur n'est autorisé qu'à un seul `CustomData` pour chaque `index` unique. Ajouter un autre `CustomData` avec le même `index` remplacera le `CustomData` existant.
  * L'`index` de custom data peut être trouvé dans le [Custom Data dashboard](/user-manual/assets/custom-data/manage-custom-data) sous la colonne « INDEX ».
  * Pour empêcher le SDK d'envoyer les données avec l'index sélectionné aux serveurs Kameleoon pour des raisons de confidentialité, activez l'option **Use this data only locally for targeting purposes** lors de la création de la custom data.
  * Ajouter une instance de `CustomData` créée avec un nom alors que la configuration de l'instance du SDK n'est pas à jour ou que le nom n'est pas enregistré, entraînera l'ignorance des données.
</Note>

```swift theme={null}
kameleoonClient.addData(CustomData(index: 1, values: "value"))

// With several values
kameleoonClient.addData(CustomData(index: 1, values: "value 1", "value 2"))

// To set the 'overwrite' flag to false
kameleoonClient.addData(CustomData(index: 1, overwrite: false, values: ["first value", "second value"]))

// To use a name instead of the index
kameleoonClient.addData(CustomData(name: "my-custom-data", values: "value"))
```

#### Device

<Note>
  Depuis le SDK iOS `4.14.0`, le `Device` est automatiquement détecté en fonction de la valeur de [`UIDevice.current.userInterfaceIdiom`](https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom). Cependant, vous pouvez toujours le remplacer manuellement si nécessaire.
</Note>

Stocke des informations sur l'appareil de l'utilisateur.

| Nom    | Type   | Description                                                              |
| ------ | ------ | ------------------------------------------------------------------------ |
| device | Device | Liste des appareils : `phone`, `tablet`, `desktop`. Ce champ est requis. |

```swift theme={null}
try? kameleoonClient.addData(Device.desktop);
```

#### Geolocation

`Geolocation` contient les détails de géolocalisation du visiteur.

| Nom                      | Type                   | Description                                                                                                                  |
| ------------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| country (*requis*)       | `String`               | Le pays du visiteur.                                                                                                         |
| region (*optionnel*)     | <nobr>`String?`</nobr> | La région du visiteur.                                                                                                       |
| city (*optionnel*)       | <nobr>`String?`</nobr> | La ville du visiteur.                                                                                                        |
| postalCode (*optionnel*) | <nobr>`String?`</nobr> | Le code postal du visiteur.                                                                                                  |
| latitude (*optionnel*)   | `Double?`              | La coordonnée de latitude représentant la localisation du visiteur. Le nombre de coordonnée représente des degrés décimaux.  |
| longitude (*optionnel*)  | `Double?`              | La coordonnée de longitude représentant la localisation du visiteur. Le nombre de coordonnée représente des degrés décimaux. |

<Tip>
  * Chaque visiteur ne peut avoir qu'une seule `Geolocation`. Ajouter une deuxième `Geolocation` écrase la première.
</Tip>

```swift theme={null}
kameleoonClient.addData(Geolocation(country: "France", region: "Île-de-France", city: "Paris"));
```

### Types renvoyés

#### DataFile

Le `DataFile` contient les détails de configuration du SDK.

Il peut être étendu avec des informations supplémentaires si requis par les clients. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom          | Type                    | Description                                                                       |
| ------------ | ----------------------- | --------------------------------------------------------------------------------- |
| featureFlags | `[String: FeatureFlag]` | Un map d'objets [`FeatureFlag`](#featureflag), indexés par clés de feature flag.  |
| dateModified | `Int`                   | Le timestamp (en millisecondes) indiquant la dernière modification du `DataFile`. |

```swift theme={null}
// Retrieves the dictionary of feature flags from the DataFile.
// The dictionary is keyed by feature flag identifiers, with each value being a FeatureFlag object.
let featureFlags = dataFile.featureFlags

// Retrieves the last modification timestamp of the DataFile.
// The value is an Int representing milliseconds since the Unix epoch.
let dateModified = dataFile.dateModified
```

#### FeatureFlag

Le `FeatureFlag` représente un ensemble de propriétés qui définissent un feature flag lui-même — par exemple, ses [`Variations`](#variation), [`Rules`](#rule), statut d'environnement et autres détails connexes.

Il peut être étendu avec des informations supplémentaires si requis par les clients. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom                 | Type                  | Description                                                        |
| ------------------- | --------------------- | ------------------------------------------------------------------ |
| environmentEnabled  | `Bool`                | Indique si le feature flag est activé dans l'environnement actuel. |
| defaultVariationKey | `String`              | La clé de la variation par défaut associée au feature flag.        |
| variations          | `[String: Variation]` | Un map d'objets `Variation`, indexés par clés de variation.        |
| rules               | `[Rule]`              | Une liste d'objets `Rule`                                          |

```swift theme={null}
// Check whether the feature flag is enabled in the current environment
let isEnvironmentEnabled = featureFlag.environmentEnabled

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

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

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

// Retrieve all targeting rules associated with the feature flag
let rules = featureFlag.rules
```

#### Rule

La `Rule` représente un ensemble de propriétés qui définissent une règle elle-même — par exemple, ses [`Variations`](#variation).

Elle peut être étendue avec des informations supplémentaires si requis par les clients. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom        | Type                  | Description                                                 |
| ---------- | --------------------- | ----------------------------------------------------------- |
| variations | `[String: Variation]` | Un map d'objets `Variation`, indexés par clés de variation. |

```swift theme={null}
// Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
let variations = rule.variations
```

#### Variation

`Variation` contient des informations sur la variation attribuée au visiteur (ou la variation par défaut, si aucune attribution spécifique n'existe).

| Nom          | Type                 | Description                                                                                                                                                          |
| ------------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name         | `String`             | Le nom de la variation.                                                                                                                                              |
| key          | `String`             | La clé unique identifiant la variation.                                                                                                                              |
| id           | `Int`                | L'ID de la variation attribuée (ou `-1` s'il s'agit de la variation par défaut).                                                                                     |
| experimentId | `Int`                | L'ID de l'expérience associée à la variation (ou `-1` si par défaut).                                                                                                |
| variables    | `[String: Variable]` | Un map contenant les variables de la variation attribuée, indexés par noms de variable. `variables` peut être une collection vide si aucune variable n'est associée. |

<Note>
  * L'objet `Variation` fournit des détails sur la variation attribuée et son expérience associée, tandis que l'objet [`Variable`](#variable) contient des détails spécifiques sur chaque variable au sein d'une variation.
  * Assurez-vous que votre code gère le cas où `id` ou `experimentId` peut être `-1`, indiquant une variation par défaut.
  * Le map `variables` peut être vide si aucune variable n'est associée à la variation.
</Note>

```swift theme={null}
// Retrieving the variation name
let variationName = variation.name

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

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

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

// Retrieving the variables map
let variables = variation.variables
```

#### Variable

`Variable` contient des informations sur une variable associée à la variation attribuée.

| Nom   | Type     | Description                                                                                                                                                                 |
| ----- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| key   | `String` | La clé unique identifiant la variable.                                                                                                                                      |
| type  | `String` | Le type de la variable. Valeurs possibles : **BOOLEAN**, **NUMBER**, **STRING**, **JSON**.                                                                                  |
| value | `Any?`   | La valeur de la variable, qui peut être de l'un des types suivants : **Bool**, **Int**, **Double**, **String**, **\[String: Any]** (objet json), **\[Any]** (tableau json). |

```swift theme={null}
// Retrieving the variables map
let variables = variation.variables

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

// Get the bool value of "isDiscount" (default to false if missing or not a Bool)
let isDiscount = variables["isDiscount"]?.value as? Bool ?? false

// Get the numeric value of "number" as an Int (default to 0 if missing or not numeric)
let number = (variables["number"]?.value as? NSNumber)?.intValue ?? 0

// Get the String value of "title" (default to an empty string if missing or not a String)
let title = variables["title"]?.value as? String ?? ""
```

### Méthodes dépréciées

<Warning>
  Ces méthodes sont dépréciées et seront supprimées dans la version `5.0.0` du SDK.
</Warning>

#### getFeatureVariationKey()

* 📨 *Envoie des données de tracking à Kameleoon*

<Note>
  Utilisez plutôt [`getVariation()`](#getvariation).
</Note>

Utilisez cette méthode pour obtenir la clé de [variation de fonctionnalité](/user-manual/experimentation/feature-experimentation/configure-your-feature-flags/define-feature-variations) pour un utilisateur spécifique. Cette méthode prend un `featureKey` comme argument requis pour récupérer la clé de variation pour l'utilisateur spécifié.

Si le visiteur n'a jamais été associé à ce feature flag, le SDK renvoie une clé de variation attribuée aléatoirement (selon les règles du feature flag). Si le visiteur est déjà enregistré avec ce feature flag, cette méthode renvoie la clé de variation précédente. Si le visiteur ne correspond à aucune des règles, la variation par défaut que vous avez définie dans l'application Kameleoon sera renvoyée.

Assurez-vous de configurer une gestion appropriée des erreurs comme indiqué dans l'exemple de code pour capturer les erreurs potentielles.

```swift theme={null}
let featureKey = "new_checkout"
var variationKey = ""

do {
	variationKey = try kameleoonClient.getFeatureVariationKey(featureKey: featureKey)
    switch variationKey {
        case "variation 1":
            // The visitor has been bucketed with variation 1 key
        case "variation 2":
            // The visitor has been bucketed with variation 1 key
        default:
            //The visitor has been bucketed with the default variation or is part of the unallocated traffic sample
    }
} catch {
    switch error {
        case KameleoonError.sdkNotReady:
            // Exception indicating that the SDK has not completed its initialization yet.
        case KameleoonError.Feature.notFound:
		    // The feature key is not in the configuration file that has been fetched by the SDK. Trigger the old checkout for this visitor.
        case KameleoonError.Feature.environmentDisabled:
		    // The feature flag is disabled for the environment.
        default:
            // Any other error.
    }
}
```

#### getActiveFeatureList()

<Note>
  Utilisez plutôt [`getVariations()`](#getvariations).
</Note>

Pour obtenir la liste des clés de feature flag actuellement disponibles et actives pour le visiteur.

```swift theme={null}
let activeFeatureFlags = kameleoonClient.getActiveFeatureList()
```

##### Valeur de retour

| Type      | Description                                            |
| --------- | ------------------------------------------------------ |
| \[String] | Liste de clés de feature flag actives pour le visiteur |

#### getActiveFeatures()

<Note>
  Utilisez plutôt [`getVariations()`](#getvariations).
</Note>

La méthode `getActiveFeatures` récupère des informations sur les feature flags actifs disponibles pour le visitor code spécifié.

```swift theme={null}
let activeFeatures = kameleoonClient.getActiveFeatures()
```

##### Valeur de retour

| Type                        | Description                                                                                                                                                          |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `[String: Types.Variation]` | Un dictionnaire contenant les variations attribuées au visiteur pour chaque fonctionnalité active en utilisant les clés des fonctionnalités actives correspondantes. |

#### getFeatureVariable()

* 📨 *Envoie des données de tracking à Kameleoon*

<Note>
  - Utilisez plutôt [`getVariation()`](#getvariation).
  - Cette méthode s'appelait auparavant `obtainFeatureVariable()`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Appelez cette méthode pour obtenir la [variable de fonctionnalité](/user-manual/experimentation/feature-experimentation/configure-your-feature-flags/define-feature-variables) d'une clé de variation associée à un utilisateur.

Cette méthode prend `featureKey` et `variableKey` comme arguments requis pour obtenir la variable de la clé de variation pour un utilisateur donné.

Si un visiteur n'a jamais été associé à ce feature flag, le SDK renvoie une valeur de variable pour la clé de variation qu'il attribue aléatoirement selon les règles du feature flag. Si l'utilisateur est déjà enregistré avec ce feature flag, le SDK renvoie la valeur de variable pour la variation précédemment associée. Si l'utilisateur ne correspond à aucune des règles, la variable par défaut est renvoyée.

```swift theme={null}
String featureKey = "myFeature"
String variableKey = "myVariable"

try {
	let variable = kameleoonClient.getFeatureVariable(featureKey: featureKey, variableKey: variableKey)
    // your custom code, depending on variableValue
} catch {
    switch error {
        case KameleoonError.sdkNotReady:
            // Exception indicating that the SDK has not completed its initialization.
        case KameleoonError.Feature.notFound:
		    // The Feature Key is not in the configuration file that has been fetched by the SDK. Trigger the old checkout for this visitor.
        case KameleoonError.Feature.environmentDisabled:
		    // The feature flag is disabled for the environment.
        case KameleoonError.Feature.variableNotFound:
            // Exception indicating that the requested variable has not been found. Check that the variable's key matches the one in your code.

        default:
            // Any other error.
    }
}
```

##### Arguments

| Nom         | Type   | Description                                                                                  |
| ----------- | ------ | -------------------------------------------------------------------------------------------- |
| featureKey  | String | Clé d'identification de la fonctionnalité que vous souhaitez récupérer. Ce champ est requis. |
| variableKey | String | Nom de la variable pour laquelle vous souhaitez obtenir une valeur. Ce champ est requis.     |

##### Valeur de retour

| Type | Description                                                                                                                                       |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Any  | Données associées à ce feature flag. Les valeurs peuvent être `Int`, `String`, `Bool` ou `Dictionary` (selon le type défini sur l'interface web). |

##### Erreurs levées

| Type                                           | Description                                                                                                                                                                                                                                                                                                     |
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| KameleoonError.sdkNotReady                     | Exception indiquant que le SDK n'est pas entièrement initialisé.                                                                                                                                                                                                                                                |
| KameleoonError.Feature.notFound                | Exception indiquant que l'ID de fonctionnalité demandé n'a pas été trouvé dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas encore été activé du côté de Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application web). |
| KameleoonException.Feature.environmentDisabled | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                                                                                                                |
| KameleoonError.Feature.variableNotFound        | Exception indiquant que la variable demandée n'a pas été trouvée. Vérifiez que la clé de la variable dans l'application Kameleoon correspond à la clé dans votre code.                                                                                                                                          |

#### getFeatureVariationVariables()

<Note>
  * Utilisez plutôt [`getVariation()`](#getvariation).
  * Cette méthode s'appelait auparavant `getFeatureAllVariables`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Pour récupérer toutes les variables d'une fonctionnalité, appelez cette méthode. Vous pouvez modifier vos variables de fonctionnalité dans l'application Kameleoon.

Cette méthode prend `featureKey` comme argument. Elle renvoie des données avec le type `[String: Any]`, comme défini sur l'interface web. Elle lèvera une exception (`KameleoonError.Feature.notFound`) si la fonctionnalité demandée n'a pas été trouvée dans la configuration interne du SDK.

```swift theme={null}
let featureKey = "myFeature"
let variationKey = "on"

do {
	allVariables = try kameleoonClient.getFeatureVariationVariables(featureKey: featureKey, variationKey: variationKey);
} catch KameleoonError.Feature.notFound {
	// The feature is not activated in Kameleoon.
} catch KameleoonError.Feature.environmentDisabled {
	// The feature flag is disabled for the environment.
} catch  {
    // This is a generic Exception handler that will handle all errors.
}
```

##### Arguments

| Nom          | Type   | Description                                                                                  |
| ------------ | ------ | -------------------------------------------------------------------------------------------- |
| featureKey   | String | Clé d'identification de la fonctionnalité que vous souhaitez récupérer. Ce champ est requis. |
| variationKey | String | La clé de la variation que vous souhaitez récupérer. Ce champ est requis.                    |

##### Valeur de retour

| Type           | Description                                                                                                                                       |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| \[String: Any] | Données associées à ce feature flag. Les valeurs peuvent être `Int`, `String`, `Bool` ou `Dictionary` (selon le type défini sur l'interface web). |

##### Erreurs levées

| Type                                           | Description                                                                                                                                                                                                                                                                                                                                                              |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| KameleoonError.sdkNotReady                     | Exception indiquant que le SDK n'est pas entièrement initialisé.                                                                                                                                                                                                                                                                                                         |
| KameleoonError.Feature.notFound                | Exception indiquant que l'ID de fonctionnalité demandé n'a pas été trouvé dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas été activé dans l'application Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application web).                                                         |
| KameleoonException.Feature.environmentDisabled | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                                                                                                                                                                         |
| KameleoonError.Feature.variationNotFound       | Exception indiquant que la clé de variation demandée n'a pas été trouvée dans la configuration interne du SDK. Cette exception signifie que le feature flag n'a pas encore été récupéré par le SDK, ce qui peut se produire si le SDK est en mode [polling](/fr/developer-docs/feature-experimentation/technical-reference/technical-considerations#polling-par-defaut). |

```swift theme={null}
let featureKey = "myFeature"
let variationKey = "on"

do {
	allVariables = try kameleoonClient.getFeatureVariationVariables(featureKey: featureKey, variationKey: variationKey);
} catch KameleoonError.Feature.notFound {
	// The feature is not activated in Kameleoon.
} catch KameleoonError.Feature.environmentDisabled {
	// The feature flag is disabled for the environment.
} catch  {
    // This is a generic Exception handler that will handle all errors.
}
```
