# On your website

Use The Wallet Crew **cinto SDK** to place an **“Add to Wallet”** button on any web page. Your customers can save a pass to **Apple Wallet** or **Google Wallet** directly from your site, without being sent to a separate app or flow.

The SDK detects the device and renders the right CTA automatically. On iOS it shows “Add to Apple Wallet”. On Android it shows “Add to Google Wallet”. On desktop it can fall back to a hosted page (or a QR code flow if you prefer).

<details>

<summary><strong>Real-world examples</strong></summary>

* A loyalty account page includes “Add to Wallet” next to the membership number.
* A checkout confirmation page lets customers save their gift card instantly.
* A “My tickets” page renders one button per event ticket, on mobile.

</details>

<figure><img src="https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-7e36be813a89e58f7b201e3634f0b45775ea383b%2Fillustration-add-to-wallet-sdk-integration.png?alt=media" alt="Embed “Add to Wallet” button in a web page."><figcaption></figcaption></figure>

### UI Result

**On iOS mobile device**

![On iOS mobile device](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-4b2b4dc433d0fbdea19275dc6460ba49861218a9%2Fon_your_website_1.png?alt=media)

**On Android mobile device**

![On Android mobile device](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-55016ae6afd50971f75cd296693d4747b442a565%2Fon_your_website_2.png?alt=media)

**Otherwise**

![Otherwise](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-5b57567f4f2f971a0e4003b97fdfaf8deacbc355%2Fon_your_website_3.png?alt=media)

This button redirects the user to The Wallet Crew pass layout which looks like this :

![UI Result](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-c39073618a273611dbf894db814a309df6d11c9c%2Fon_your_website_4.png?alt=media)

📌 It is possible to change this behavior and display the QRCode with a text in place of the button.

### How to display the button ?

**Through vanilla javascript**

```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>

```

The third parameter may contains any option available for The Wallet Crew, to force a language use

```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>

```

**Through npm module**

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

```jsx
// install cinto SDK through npm install @neostore/cinto
import { AddToWalletButton } from "@neostore/cinto";

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

```

**Options**

```tsx
export interface Options {
    /**
     * Neostore URI environment to use.
     * @default: <https://app.neostore.cloud>
     */
    environment: string;
    /**
     * Identifier of the tenant.
     */
    tenantId: string;
    /**
     * Name of the pass layout to redirect the user when the user is on desktop
     * @default: pass
     */
    passLayoutName: string;
    /**
     * ISO 639 language code to use to do display the button. When omitted, the language will be automatically detected based on the browser settings.
     * If the value doesn't match any available option, the browser settings will be used otherwise english will be used.
     * @default: undefined
     */
    language?: string;
    /**
     * Identifier of the pass to display or promise of it
     */
    passId: string;
    /**
     * Platform to use to display the button. When omitted, the platform will be automatically detected based on the user agent.
     * Possible values are: "apple", "google" or "desktop"
     *
     * @default: undefined
     **/
    platform?: Platform;
    /**
     * External identifiers to use to aquire the passId
     */
    externalIdentifiers?: Record<string, { value: string; hmac?: string }>;
    /**
     * Pass type to use to aquire the passId
     * Required when externalIdentifiers is set
     */
    passType?: string;
    
    /**
     * Source used for analytics purpose
     */
    source?: {
        /**
         * list of tags to associate to this download. utm_source and utm_campaign will automatically be aggregated to this list
         */
        tags?: Array<string>;
        /**
         * medium to associate to this download. utm_medium will be used if no value is specified
         */
        medium?: string;
        /**
         * origin to associate to this download. the current url (without query) will be used if no value is specified
         */
        origin?: string;
    };

    /**
     * Callback called when the button is clicked
     */
    onClick?: (e: MouseEvent, data: { options: Partial<Options>; platform: Platform }) => void;

    /**
     * Callback when an error occurs
     *
     */
    onError?: (error: string) => void;
}

```

#### Concepts

**Platform detection**

When using the `data-neostore-addToWalletButton` data attribute, the component will automatically render the right button with the defined callback:

* desktop: redirects to the pass page from The Wallet Crew
* apple: displays the add to wallet call to action that downloads the pass
* android: displays the add to google wallet that opens the google page

This can be overriden by using `data-neostore-platform="desktop"` ("desktop", "apple", or "google" options)

**Language detection**

The component is looking for the user browser's language and fallback to en either if the locale doesn't exist for the given platform or if the user language is not supported.

You can force the language by using `data-neostore-language="fr"`

**Customization**

The general layout is:

* a div of your responsibility
  * a link, selector: `.neostore-link`
    * an image, selector `.neostore-img` and `.neostore-link-{{ platform }}` where platform is desktop, apple, android

The android and google buttons respects the google and apple design guidelines for this action. [Apple guideline](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/){target="\_blank"} [Google Guideline](https://developers.google.com/wallet/generic/resources/brand-guidelines){target="\_blank"}

You can still update some styles using css but remember that the link contains an image.

#### Advanced usage

**desktop render customization**

On desktop, the principal information is the url where you should redirect your users. You can update the way you render this link to display a QR Code for example using the following snippet

```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", {
        passType: "user",
        passId: 'KlnqcxVLA9pS4ol5'
    });
    const url = await button.getPassPageUrl();
    new QRCode(document.getElementById("qrcode"), url);
</script>

```

**using external identifiers with hmac**

You can retrieve the `passId` parameters through The Wallet Crew API. It is also possible to use the `externalIdentifiers` and the hmac\_sha256 value of the identifiers.

hmac\_sha256 should be computed with one of The Wallet Crew secret.

For example, for a customerId of `SC103010` and a secret of `I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ` the hmac value should be `8c5a9ebdd9b4ac8d2307cc34192f0faed441ef724c043162f0618784173d4d93`

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

Exemple of hmac computing

**using data-attribute**

```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>

```

Attributes are interpreted as lower case string by the browser. To include uppercase character prefix the character with the underscore sign : `y2.customer_Id` will be interpreted as `y2.customerId`

**using component**

```jsx
// install cinto SDK through npm install @neostore/cinto
import { AddToWalletButton } from "@neostore/cinto";

const btn = new AddToWalletButton("molia", {
    language: "fr",
    externalIdentifiers: {
        "y2.customerId": {
            value: "SC103010",
            // hmac_sha256 of customerId with one of the neostore secret
            hmac: "cbbcfc5xxxxx",
        },
    },
});
btn.render(document.getElementById("btn"));

```

### How to add analytics information ?

It is possible to specify 3 installation information that will be available in the `Pass:Installed` event used by the dashboard and the insights API.

* `tags` : an array of string used to determine the source of this download - the utm\_source and utm\_campaign will automatically concatenated to the tags
* `medium`: a string used to determine the medium of this download. It could be anything for example `ecomm` or `mobileapp`, etc.
* `origin`: by default the url (without search parameter) of the page where the add to wallet button is used. it is possible to overrides this value

these value can be specified like this

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

all parameters are optional

### How to get passId information ?

#### When the pass already exists

![When the pass already exists](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-6a87c522885def06a6e2bd4ce760a87fac57522b%2Fon_your_website_5.png?alt=media)

1. **Get an API Key on The Wallet Crew back-office :**
   1. <https://admin.thewalletcrew.io/tenant/\\~/apiKeys>
   2. API Key should have the `tenant.pass:read` permission

![When the pass already exists (2)](https://3566051324-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWLc8AHXW4tdrAXUBfrYF%2Fuploads%2Fgit-blob-8145ec645d8ac7afb5ab379143e793c724611171%2Fon_your_website_6.png?alt=media)

2. **Call the /passes API**

   `https://app.neostore.cloud/api/{tenantId}/passes?filter=filter[0].field=y2.customerId&filter[0].operator=equals&filter[0].value=04101234`

   \*\*`curl -X 'GET' \ 'https://app.neostore.cloud/api/{tenantId}/passes?filter%5B0%5D.field%3Dy2.customerId%26filter%5B0%5D.operator%3Dequals%26filter%5B0%5D.value%**04101234**\ -H 'accept: text/plain' \ -H 'X-API-KEY: {apiKey}'**`

   **Result will be something like:**

   ```jsx
   [
   	{
   		"id": "KlnqcxVLAxxxxxx",
   		"secret": "r9vuaWOxxxxxxx",
   		"creationDate": "2023-07-19T11:56:34.9418747Z",
   		"passType": "user",
   		"identifiers": {
   			"y2.customerId": "04101234"
   		},
   		"providers": {
   			"apple": {
   				"installationDate": "2023-07-19T11:56:43.2830295Z",
   				"devices": [
   					{
   						"deviceIdentifier": "5dec2xxxxxx",
   						"pushToken": "5f7f23xxxxx",
   						"registrationDate": "2023-07-19T11:56:43.2830295Z"
   					}
   				]
   			}
   		}
   	}
   ]
   ```

#### When the pass doesn’t exists

### Third party integration

#### Shopify

use this liquid placeholder to display the add to wallet button :

```jsx
{% assign tenantId = 'molia' %}
{% assign secret = 'sTyQrYOKtkIfT77K4wns8cUxfOTV7n57RFztd59wPNqvyvZ9sNnCy3a3s8cikz9z' %}

{% assign y2Identifier = 'SC103010' %}
{% assign y2Identifierhmac = y2Identifier | hmac_sha256: secret %}

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

<div
  data-neostore-addToWalletButton
  data-neostore-passType='user'
  data-neostore-externalIdentifiers='{"y2.customerId":{"value":"{{ y2Identifier }}","hmac":"{{ y2Identifierhmac }}"} }'>
</div>
```

#### React integration

It is possible to encapsulate the button within React using this component. You can adjust your component based on your needs :

```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;
```


---

# Agent Instructions: 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:

```
GET https://docs.thewalletcrew.io/enroll/on-your-website.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
