> 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

**cinto** est le SDK JavaScript de The Wallet Crew pour intégrer des boutons Add to Wallet sur n'importe quelle page web. Utilisez-le pour placer un **Add to 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 une solution de repli basée sur un QR code.

<details>

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

* Une page de compte 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, pas un bouton par commande.

</details>

<figure><img src="/files/8afcc3e12768ffb23b7213e089cc854009315fa6" 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 aux ordinateurs.</p></figcaption></figure>

## Comment fonctionne l'intégration sur le 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 correspondant 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" %}
N'utilisez jamais la même valeur d'identifiant statique pour chaque client. Si le même `customerId`, l'identifiant de billet ou la valeur de recherche de carte est codé 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 approprié :

* **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="/files/b176e29707d45b3fd06d8d9a0b1c80285cbeccf0" alt="Bouton Ajouter à Apple Wallet affiché sur iPhone." width="250">

**Android**

<img src="/files/157c4811417ed857842d7aa7a9519031dd9d66fd" alt="Bouton Ajouter à Google Wallet affiché sur Android." width="250">

**Ordinateur**

<img src="/files/e7146c77b8f98aa5aac7daaccdc3b75f8fbf2732" alt="Rendu de secours sur ordinateur pour Add to Wallet." width="250">

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

![Page de carte hébergée utilisée comme solution de secours sur ordinateur pour la distribution sur site web.](/files/4aa61a8db57108876a766b0ca2c28d81736b3456)

{% hint style="info" %}
Le comportement sur ordinateur peut être personnalisé pour afficher un code QR au lieu 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 avec `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 générique `https://app.neostore.cloud` peut aussi ê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 pour la production.
{% endhint %}

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

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

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

```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 encore 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 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 mettent les noms d'attributs HTML en minuscules. Pour préserver 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 n'affecte que le nom de l'attribut HTML. Elle ne modifie pas la valeur signée.

## Comportement 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 de JavaScript vanilla

```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 aussi ê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 vers laquelle 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 détectée automatiquement selon les 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 associée
     */
    passId: string;
    /**
     * Plateforme à utiliser pour afficher le bouton. Lorsqu'elle est omise, la plateforme sera détectée automatiquement à partir du user agent.
     * 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 tags à associer à ce téléchargement. utm_source et utm_campaign seront automatiquement ajoutés à cette liste
         */
        tags?: Array<string>;
        /**
         * support à 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 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 lorsqu'une erreur se produit
     *
     */
    onError?: (error: string) => void;
}

```

### Style

La structure rendue est :

* un conteneur fourni par le site web
  * un lien avec sélecteur `.neostore-link`
    * une image avec des 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 consignes 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 éléments de bouton Apple et Google suivent les consignes de chaque fournisseur :

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

## Personnalisation du bureau

Sur ordinateur, le résultat le plus important est l’URL de la Carte hébergée. Cette URL peut être utilisée pour afficher un code QR à la place 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.getPassPageUrl();
    new QRCode(document.getElementById("qrcode"), url);
</script>
```

## Ajouter des informations d'analyse

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

* `balises`: liste des balises source. `utm_source` et `utm_campaign` sont ajoutés automatiquement.
* `moyen`: libellé de canal tel que `e-commerce` ou `compte`.
* `origine`: 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="e-commerce"
     data-neostore-src-origin="originA"
 ></div>
```

## Récupérer `passId` lorsque 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éez une clé API dans la console d’administration avec `tenant.carte:read`.

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

{% step %}

### Interroger 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 doit renvoyer 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 %}

### Rendre le bouton avec `passId`

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

## Exemple d’intégration tierce

<details>

<summary><strong>Exemple d’enveloppe 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 selon le client, le billet ou le 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 dispose d’un identifiant stable et que la Carte doit être résolue dynamiquement.

</details>

<details>

<summary><strong>Plusieurs boutons peuvent-ils être rendus 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 rendez un bouton par Carte.

</details>

<details>

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

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

</details>

<details>

<summary><strong>Quand faut-il utiliser plutôt 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 [Dans votre application mobile](/guides-enrolment/fr/inscription/readme-1.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.
