> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/guides-enrolment/fr/inscription/on-your-website.md).

# Sur votre site web

Intégrez un bouton Ajouter à Wallet sur le site web d’une marque avec le SDK cinto de The Wallet Crew, y compris la détection Apple/Google et une solution de repli pour ordinateur.

**cinto** est le SDK JavaScript de The Wallet Crew pour intégrer des boutons Ajouter à Wallet sur n’importe quelle page web. Utilisez-le pour placer un **Ajouter à Wallet** bouton sur n’importe quel site web — le SDK détecte l’appareil et affiche automatiquement le bon appel à l’action.

Sur iOS, il affiche **Ajouter à Apple Wallet**. Sur Android, il affiche **Ajouter à Google Wallet**. Sur ordinateur, il peut rediriger vers une page de carte hébergée ou prendre en charge un repli basé sur un code QR.

<details>

<summary><strong>Exemples concrets</strong></summary>

* Une page de compte de fidélité affiche un bouton pour la carte du client connecté.
* Une section de cartes cadeaux affiche un bouton par carte cadeau active.
* Une page de billetterie affiche un bouton par billet, et non un bouton par commande.

</details>

<figure><img src="https://831874859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlFokgwgJiwLXu7G8MVSJ%2Fuploads%2FQnCNBcX4i6sfADfIDZgy%2Fillustration-add-to-wallet-sdk-integration.png?alt=media&#x26;token=8f676cd5-9bcb-47e7-ac27-53614518f730" alt="Add to Wallet button embedded on a website with device-specific rendering."><figcaption><p>La même intégration adapte le bouton à iOS, Android et sur ordinateur.</p></figcaption></figure>

## Comment fonctionne l’intégration sur un site web

L’intégration est simple. Une page charge le SDK cinto, puis affiche un bouton qui résout une carte.

Cette carte peut être résolue de deux façons :

* avec un `passId`
* avec `externalIdentifiers` et un HMAC facultatif

### Chaque carte doit être unique

Ce point est crucial. Une carte Wallet est **pas** une ressource partagée.

Chaque carte doit représenter un client, une carte, un billet ou une instance de droit d’accès. Le bouton affiché sur une page doit résoudre uniquement la carte qui appartient au contexte actuel.

Par exemple :

* une page de carte de fidélité doit résoudre la carte du client actuel
* une liste de billets doit résoudre une carte distincte par billet
* une liste de cartes cadeaux doit résoudre une carte distincte par carte cadeau

{% hint style="warning" %}
Ne réutilisez jamais la même valeur d’identifiant statique pour chaque client. Si le même `customerId`, l’identifiant du billet ou la valeur de recherche de carte est codée en dur pour tous les visiteurs, la même carte peut être renvoyée à tout le monde.
{% endhint %}

Lorsque `externalIdentifiers` sont utilisés, la valeur de l’identifiant doit être suffisamment unique pour résoudre **exactement une carte**. Si une recherche renvoie plusieurs cartes, la stratégie d’identifiant n’est pas assez spécifique pour une distribution sur site web.

### Ce qui change selon l’appareil

Le SDK affiche automatiquement le comportement correct :

* **iOS :** télécharge la carte Apple Wallet
* **Android :** ouvre le flux d’enregistrement Google Wallet
* **Ordinateur :** redirige vers une page de carte hébergée

Ce comportement par défaut peut être remplacé si nécessaire avec `platform`.

#### Exemple de rendu

**iOS**

<img src="https://831874859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlFokgwgJiwLXu7G8MVSJ%2Fuploads%2F7BgqaHarZQ0jXz0tlQ8k%2Fenroll-website-ios-mobile-device.png?alt=media&#x26;token=6bc7b7c8-532a-4865-9ecc-e2a723e75aec" alt="Bouton Ajouter à Apple Wallet affiché sur iPhone." width="250">

**Android**

<img src="https://831874859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlFokgwgJiwLXu7G8MVSJ%2Fuploads%2Fc5UFGREPwkZ2pYKfhidd%2Fenroll-website-android-mobile-device.png?alt=media&#x26;token=d34e7b68-dd15-4054-8b99-69039334a494" alt="Bouton Ajouter à Google Wallet affiché sur Android." width="250">

**Ordinateur**

<img src="https://831874859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlFokgwgJiwLXu7G8MVSJ%2Fuploads%2FvpVCqxoxVNTk6kbijj5C%2Fenroll-website-otherwise.png?alt=media&#x26;token=c7a33eb9-96c2-417f-9fb6-97f13584bdaa" alt="Rendu de secours sur ordinateur pour Ajouter à Wallet." width="250">

Le repli sur ordinateur ouvre une page de carte hébergée telle que :

<figure><img src="https://831874859-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FlFokgwgJiwLXu7G8MVSJ%2Fuploads%2F2XHK45WZLt2FhuIHebvw%2Fenroll-website-ui-result.png?alt=media&#x26;token=8efaa7d7-c727-4b2c-b107-e466a35accc5" alt="Hosted pass page used as desktop fallback for website distribution."><figcaption><p>Vérifiez que la page de carte hébergée résout la carte attendue pour le contexte actuel.</p></figcaption></figure>

{% hint style="info" %}
Le comportement sur ordinateur peut être personnalisé pour afficher un code QR à la place d’un bouton standard.
{% endhint %}

## Choisissez comment le bouton résout la carte

Le principal choix d’implémentation est la méthode de résolution de la carte.

Utilisez `passId` lorsque le backend connaît déjà la carte exacte. Utilisez `externalIdentifiers` lorsque le site web a accès à un identifiant métier stable et que la carte doit être résolue dynamiquement.

### Commencez par `tenantId` et `environment`

Deux valeurs du SDK sont particulièrement importantes :

* `tenantId`
* `environment`

`tenantId` est requis. C’est le nom du tenant dans le système The Wallet Crew. Dans les exemples de cette page, `molia` est le `tenantId`.

`environment` est l’URL de base publique utilisée par le SDK.

Utilisez ces valeurs comme suit :

* **Production :** `https://<customDomain>` le domaine générique `https://app.neostore.cloud` peut également être utilisé lorsqu’aucun domaine personnalisé n’a été configuré
* **Test / QA :** `https://app-qa.neostore.cloud`

{% hint style="info" %}
Si `environment` est omis, le SDK utilise `https://app.neostore.cloud`. Ce comportement par défaut est valide en production.
{% endhint %}

### Option 1 — Résoudre avec `passId`

C’est l’option la plus simple. Elle fonctionne le mieux lorsque le backend connaît déjà la carte exacte à afficher.

{% tabs %}
{% tab title="JavaScript pur" %}

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", {});
</script>

<div data-neostore-addToWalletButton data-neostore-passId="KlnqcxVLA9pS4ol5"></div>
```

{% endtab %}

{% tab title="module npm" %}

```bash
npm install @neostore/cinto
```

```jsx
import { AddToWalletButton } from "@neostore/cinto";

const btn = new AddToWalletButton("molia", {
    language: "fr",
    passId: "KlnqcxVLA9pS4ol5",
});

btn.render(document.getElementById("btn"));
```

{% endtab %}
{% endtabs %}

### Option 2 — Résoudre avec `externalIdentifiers`

Cette option est utile lorsque la page connaît un identifiant métier stable, comme un identifiant de fidélité, un identifiant CRM ou un identifiant de billet, mais ne connaît pas le `passId` encore.

L’identifiant doit appartenir au client ou à l’objet actuel. Il ne doit pas s’agir d’une constante partagée.

Lorsque HMAC est utilisé, la signature doit être calculée côté serveur avec l’un des secrets de The Wallet Crew.

Par exemple, pour un `customerId` de `SC103010` et un secret de `I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ`, la valeur HMAC est :

`8c5a9ebdd9b4ac8d2307cc34192f0faed441ef724c043162f0618784173d4d93`

Outil de référence : [CyberChef](https://gchq.github.io/CyberChef/#recipe=HMAC\({'option':'UTF8','string':'I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ'},'SHA256'\)\&input=U0MxMDMwMTA)

{% hint style="warning" %}
Le secret HMAC doit rester côté serveur. Il ne doit jamais être exposé dans le code du navigateur.
{% endhint %}

#### Attributs de données

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", { language: "fr" });
</script>

<div data-neostore-addToWalletButton
     data-neostore-passType="user"
     data-neostore-externalIdentifiers-y2.customer_Id-value="SC103010"
     data-neostore-externalIdentifiers-y2.customer_Id-hmac="cbbcfc5xxxxx"
 ></div>
```

#### Utilisation du composant

```jsx
import { AddToWalletButton } from "@neostore/cinto";

const btn = new AddToWalletButton("molia", {
    language: "fr",
    passType: "user",
    externalIdentifiers: {
        "y2.customerId": {
            value: "SC103010",
            hmac: "cbbcfc5xxxxx",
        },
    },
});

btn.render(document.getElementById("btn"));
```

#### Casse des clés d’identifiant en HTML

Les navigateurs convertissent les noms d’attributs HTML en minuscules. Pour conserver une majuscule dans une clé d’identifiant, préfixez le caractère avec `_` dans le nom de l’attribut.

Exemple :

* `y2.customer_Id` devient `y2.customerId`

Cette règle ne concerne que le nom de l’attribut HTML. Elle ne modifie pas la valeur signée.

## Comportements et options courants

### Détection de la plateforme

Lorsque `data-neostore-addToWalletButton` est utilisé, le composant sélectionne automatiquement la bonne plateforme :

* `desktop`
* `apple`
* `google`

Pour forcer une plateforme, définissez `data-neostore-platform="desktop"` ou utilisez l’ `platform` option dans le composant.

### Détection de la langue

Le SDK utilise la langue du navigateur par défaut. Si la langue locale n’est pas disponible, il revient à l’anglais.

Pour forcer une langue :

* attributs de données : `data-neostore-language="fr"`
* option du composant : `language: "fr"`

Exemple JavaScript pur

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", { language: "fr" });
</script>

<div data-neostore-addToWalletButton data-neostore-passId="KlnqcxVLA9pS4ol5"></div>
```

### Options complètes

Voici la liste complète des options disponibles.

```typescript
export interface Options {
    /**
     * URL de base publique de l’environnement.
     * Utilisez "https://app-qa.neostore.cloud" pour les tests.
     * Utilisez "https://app.neostore.cloud" pour la production.
     * Un domaine personnalisé du tenant peut également être utilisé.
     * @default: "https://app.neostore.cloud"
     */
    environment: string;
    /**
     * Nom du tenant dans le système The Wallet Crew.
     * Cette valeur est requise.
     * Exemple : "molia"
     */
    tenantId: string;
    /**
     * Nom de la mise en page de carte à utiliser pour rediriger l’utilisateur lorsqu’il est sur ordinateur
     * @default: undefined // la mise en page de carte par défaut du modèle de carte sera utilisée
     */
    passLayoutName: string;
    /**
     * Code langue ISO 639 à utiliser pour afficher le bouton. Lorsqu’il est omis, la langue sera automatiquement détectée en fonction des paramètres du navigateur.
     * Si la valeur ne correspond à aucune option disponible, les paramètres du navigateur seront utilisés, sinon l’anglais sera utilisé.
     * @default: undefined
     */
    language?: string;
    /**
     * Identifiant de la carte à afficher ou promesse de celle-ci
     */
    passId: string;
    /**
     * Plateforme à utiliser pour afficher le bouton. Lorsqu’elle est omise, la plateforme sera automatiquement détectée en fonction de l’agent utilisateur.
     * Les valeurs possibles sont : "apple", "google" ou "desktop"
     *
     * @default: undefined
     **/
    platform?: Platform;
    /**
     * Identifiants externes à utiliser pour obtenir le passId
     */
    externalIdentifiers?: Record<string, { value: string; hmac?: string }>;
    /**
     * Type de carte à utiliser pour obtenir le passId
     * Requis lorsque externalIdentifiers est défini
     */
    passType?: string;
    
    /**
     * Source utilisée à des fins d’analyse
     */
    source?: {
        /**
         * liste de balises à associer à ce téléchargement. utm_source et utm_campaign seront automatiquement agrégés à cette liste
         */
        tags?: Array<string>;
        /**
         * médium à associer à ce téléchargement. utm_medium sera utilisé si aucune valeur n’est spécifiée
         */
        medium?: string;
        /**
         * origine à associer à ce téléchargement. l’URL actuelle (sans la chaîne de requête) sera utilisée si aucune valeur n’est spécifiée
         */
        origin?: string;
    };

    /**
     * Fonction de rappel appelée lorsque le bouton est cliqué
     */
    onClick?: (e: MouseEvent, data: { options: Partial<Options>; platform: Platform }) => void;

    /**
     * Fonction de rappel en cas d’erreur
     *
     */
    onError?: (error: string) => void;
}

```

### Style

La structure rendue est :

* un conteneur fourni par le site web
  * un lien avec le sélecteur `.neostore-link`
    * une image avec les sélecteurs `.neostore-img` et `.neostore-link-{{ platform }}`

Sur ordinateur, le bouton peut être entièrement personnalisé. Le résultat clé est l’URL de la carte hébergée, donc le bouton par défaut peut être remplacé par un CTA personnalisé ou un flux de code QR.

Sur mobile, le bouton doit suivre les directives de conception d’Apple et de Google. L’élément de marque, le libellé, l’espacement et la présentation globale doivent rester conformes aux exigences de chaque fournisseur.

Les ressources des boutons Apple et Google suivent les directives de chaque fournisseur :

* [Guide Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/)
* [Guide Google](https://developers.google.com/wallet/generic/resources/brand-guidelines)

## Personnalisation du bureau

Sur ordinateur, la sortie la plus importante est l’URL de la carte hébergée. Cette URL peut être utilisée pour afficher un code QR au lieu du bouton de redirection par défaut.

```html
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>

<div id="qrcode"></div>
<script type="module">
    import { AddToWalletButton } from "https://sdk.neostore.cloud/scripts/molia/cinto@1/cinto.mjs";

    const button = new AddToWalletButton("molia", {
        passId: "KlnqcxVLA9pS4ol5"
    });

    const url = await button.getCartePageUrl();
    new QRCode(document.getElementById("qrcode"), url);
</script>
```

## Ajouter des informations analytiques

Le bouton peut envoyer trois valeurs source qui seront visibles dans le `Carte:Installed` l'événement, le tableau de bord et l'API Insights.

* `tags`: liste des balises source. `utm_source` et `utm_campaign` sont ajoutés automatiquement.
* `medium`: libellé de canal tel que `ecomm` ou `compte`.
* `origin`: URL de la page source. Par défaut, l'URL de la page actuelle est utilisée sans paramètres de requête.

Toutes les valeurs sont facultatives.

```html
<div data-neostore-addToWalletButton
     data-neostore-src-tags="tag1,tag2"
     data-neostore-src-medium="ecomm"
     data-neostore-src-origin="originA"
 ></div>
```

## Récupérer `passId` quand la Carte existe déjà

Lorsque la Carte existe déjà, le backend du site web peut d’abord la rechercher, puis afficher le bouton avec la valeur renvoyée `passId`.

{% stepper %}
{% step %}

### Créer une clé API

Créer une clé API dans la console d’administration avec `tenant.Carte:read`.

Voir : [Clé API](https://docs.thewalletcrew.io/api-reference/)
{% endstep %}

{% step %}

### Interrogez le point de terminaison des Cartes

Utilisez la clé d’identifiant configurée pour rechercher la Carte.

Exemple :

```bash
curl --globoff -X GET \
  'https://app.neostore.cloud/api/<tenantId>/passes?pageIndex=0&pageSize=10&filter[0].field=identifiers.y2.customerId&filter[0].operator=equals&filter[0].value=04101234' \
  -H 'accept: application/json' \
  -H 'X-API-KEY: <apiKey>'
```

Résultat attendu :

```json
[
  {
    "id": "KlnqcxVLAxxxxxx",
    "passType": "user",
    "identifiers": {
      "y2.customerId": "04101234"
    }
  }
]
```

{% endstep %}

{% step %}

### Valider l'unicité

La recherche ne doit renvoyer qu'une seule Carte.

Si aucune Carte n’est renvoyée, la Carte n’existe pas encore. Si plusieurs Cartes sont renvoyées, l’identifiant n’est pas assez unique pour la distribution sur le site web.
{% endstep %}

{% step %}

### Affichez le bouton avec `passId`

Une fois que le `id` est connu, utilisez-le comme le `passId` dans le bouton du site web.
{% endstep %}
{% endstepper %}

## Exemple d’intégration tierce

<details>

<summary><strong>Exemple de wrapper React</strong></summary>

```tsx
import { AddToWalletButton } from "@neostore/cinto";

const CintoMobileAddToWallet = React.forwardRef<
    HTMLButtonElement,
    BoxProps & {
        passId?: string;
    }
>(({ passId, ...props }, buttonRef) => {
    const localRef = useRef<HTMLButtonElement>(null);
    buttonRef = buttonRef || localRef;

    const ctaRef = useRef<HTMLDivElement>(null);
    const cintoButtonRef = useRef<AddToWalletButton>();

    useEffect(() => {
        cintoButtonRef.current = passId
            ? new AddToWalletButton(tenantId, {
                  passId,
              })
            : undefined;
        ctaRef.current && cintoButtonRef.current?.render(ctaRef.current);
        if (passId && cintoButtonRef.current) {
            cintoButtonRef.current?.perform();
        }
    }, [passId, tenantId]);

    return (
        <Box {...props}>
            <div ref={ctaRef} />
        </Box>
    );
});

export default CintoMobileAddToWallet;
```

</details>

## FAQ

<details>

<summary><strong>Le même bouton doit-il être réutilisé pour tous les clients ?</strong></summary>

Non. Le composant visuel peut être réutilisé, mais la Carte résolue doit changer en fonction du client, du billet ou du contexte de la carte cadeau actuel.

</details>

<details>

<summary><strong>Faut-il utiliser `passId` ou `externalIdentifiers` ?</strong></summary>

Utilisez `passId` lorsque le backend connaît déjà la carte exacte. Utilisez `externalIdentifiers` lorsque la page possède un identifiant stable et que la Carte doit être résolue dynamiquement.

</details>

<details>

<summary><strong>Peut-on afficher plusieurs boutons sur la même page ?</strong></summary>

Oui. C’est courant pour les listes de billets et de cartes cadeaux. Chargez le SDK une seule fois, puis affichez un bouton par Carte.

</details>

<details>

<summary><strong>L’ordinateur de bureau peut-il afficher un code QR à la place d’une redirection standard ?</strong></summary>

Oui. L’URL de la Carte hébergée peut être utilisée pour afficher un code QR ou un autre appel à l’action spécifique au bureau.

</details>

<details>

<summary><strong>Quand faut-il plutôt utiliser une intégration d’application native ?</strong></summary>

Utilisez une intégration native lorsque le flux Wallet démarre dans une application iOS ou Android. Pour ce modèle, voir [Sur votre application mobile](/guides-enrolment/fr/inscription/on-your-mobile-app.md).

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.thewalletcrew.io/guides-enrolment/fr/inscription/on-your-website.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
