This documentation is currently under development. Certain sections are not yet complete and will be added shortly.
For the complete documentation index, see llms.txt. This page is also available as Markdown.
WebsitePass IdiOSAndroidDesktop

On your website

Embed an “Add to Wallet” button on your website with The Wallet Crew cinto SDK (Apple/Google detection + desktop fallback).

cinto is The Wallet Crew's JavaScript SDK for embedding Add to Wallet buttons on any web page. Use it to place an Add to Wallet button on any website — the SDK detects the device and renders the right call to action automatically.

On iOS, it shows Add to Apple Wallet. On Android, it shows Add to Google Wallet. On desktop, it can redirect to a hosted pass page or support a QR-based fallback.

Real-world examples
  • A loyalty account page shows one button for the logged-in customer card.

  • A gift card area shows one button per active gift card.

  • A ticketing page shows one button per ticket, not one button per order.

Add to Wallet button embedded on a website with device-specific rendering.
The same integration adapts the button to iOS, Android, and desktop.

How website embed works

The integration is simple. A page loads the cinto SDK, then renders a button that resolves one pass.

That pass can be resolved in two ways:

  • with a known passId

  • with externalIdentifiers and an optional HMAC

Each pass must be unique

This point is critical. A wallet pass is not a shared asset.

Each pass must represent one customer, one card, one ticket, or one entitlement instance. The button shown on a page must resolve the pass that belongs to the current context only.

For example:

  • a loyalty card page should resolve the current customer card

  • a ticket list should resolve one distinct pass per ticket

  • a gift card list should resolve one distinct pass per gift card

When externalIdentifiers are used, the identifier value must be unique enough to resolve exactly one pass. If a lookup returns several passes, the identifier strategy is not specific enough for website distribution.

What changes by device

The SDK renders the correct behavior automatically:

  • iOS: downloads the Apple Wallet pass

  • Android: opens the Google Wallet save flow

  • Desktop: redirects to a hosted pass page

This default can be overridden when needed with platform.

Example rendering

iOS

Add to Apple Wallet button shown on iPhone.

Android

Add to Google Wallet button shown on Android.

Desktop

Desktop fallback rendering for Add to Wallet.

The desktop fallback opens a hosted pass page such as:

Hosted pass page used as desktop fallback for website distribution.

Desktop behavior can be customized to display a QR code instead of a standard button.

Choose how the button resolves the pass

The main implementation choice is the pass resolution method.

Use passId when the backend already knows the exact pass. Use externalIdentifiers when the website has access to a stable business identifier and the pass must be resolved dynamically.

Start with tenantId and environment

Two SDK values are especially important:

  • tenantId

  • environment

tenantId is required. It is the tenant name in The Wallet Crew system. In the examples on this page, molia is the tenantId.

environment is the public base URL used by the SDK.

Use these values as follows:

  • Production: https://<customDomain> the generic https://app.neostore.cloud can also be used when no custom domain has been configured

  • Testing / QA: https://app-qa.neostore.cloud

If environment is omitted, the SDK uses https://app.neostore.cloud. This default is valid for production.

Option 1 — Resolve with passId

This is the simplest option. It works best when the backend already knows the exact pass to display.

Option 2 — Resolve with externalIdentifiers

This option is useful when the page knows a stable business identifier, such as a loyalty id, a CRM id, or a ticket id, but does not know the passId yet.

The identifier must belong to the current customer or object. It must not be a shared constant.

When HMAC is used, the signature should be computed server-side with one of The Wallet Crew secrets.

For example, for a customerId of SC103010 and a secret of I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ, the HMAC value is:

8c5a9ebdd9b4ac8d2307cc34192f0faed441ef724c043162f0618784173d4d93

Reference tool: CyberChef

Data attributes

Component usage

Identifier key casing in HTML

Browsers lowercase HTML attribute names. To preserve an uppercase character in an identifier key, prefix the character with _ in the attribute name.

Example:

  • y2.customer_Id becomes y2.customerId

This rule only affects the HTML attribute name. It does not change the signed value.

Common behavior and options

Platform detection

When data-neostore-addToWalletButton is used, the component selects the right platform automatically:

  • desktop

  • apple

  • google

To force a platform, set data-neostore-platform="desktop" or use the platform option in the component.

Language detection

The SDK uses the browser language by default. If the locale is not available, it falls back to English.

To force a language:

  • data attributes: data-neostore-language="fr"

  • component option: language: "fr"

Vanilla Javascript example

Full options

Here is the list of full available options.

Styling

The rendered structure is:

  • a container provided by the website

    • a link with selector .neostore-link

      • an image with selectors .neostore-img and .neostore-link-{{ platform }}

On desktop, the button can be fully customized. The key output is the hosted pass URL, so the default button can be replaced with a custom CTA or a QR code flow.

On mobile, the button should follow Apple and Google design guidelines. The branded asset, label, spacing, and overall presentation should stay compliant with each provider requirements.

Apple and Google button assets follow each provider guideline:

Desktop customization

On desktop, the most important output is the hosted pass URL. That URL can be used to render a QR code instead of the default redirect button.

Add analytics information

The button can send three source values that will be visible in the Pass:Installed event, the dashboard, and the Insights API.

  • tags: list of source tags. utm_source and utm_campaign are added automatically.

  • medium: channel label such as ecomm or account.

  • origin: source page URL. By default, the current page URL is used without query parameters.

All values are optional.

Retrieve passId when the pass already exists

When the pass already exists, the website backend can look it up first, then render the button with the returned passId.

1

Create an API key

Create an API key in the admin console with tenant.pass:read.

See: API Key

2

Query the passes endpoint

Use the configured identifier key to search the pass.

Example:

Expected result:

3

Validate uniqueness

The lookup should return one pass only.

If zero passes are returned, the pass does not exist yet. If several passes are returned, the identifier is not unique enough for website distribution.

4

Render the button with passId

Once the id is known, use it as the passId in the website button.

Third-party integration example

React wrapper example

FAQ

Should the same button be reused for all customers?

No. The visual component can be reused, but the resolved pass must change with the current customer, ticket, or gift card context.

Should `passId` or `externalIdentifiers` be used?

Use passId when the backend already knows the exact pass. Use externalIdentifiers when the page has a stable identifier and the pass must be resolved dynamically.

Can several buttons be rendered on the same page?

Yes. This is common for ticket lists and gift card lists. Load the SDK once, then render one button per pass.

Can desktop show a QR code instead of a standard redirect?

Yes. The hosted pass URL can be used to render a QR code or another desktop-specific CTA.

When should a native app integration be used instead?

Use a native integration when the wallet flow starts inside an iOS or Android app. For that pattern, see On your mobile app.