Shopper recognition

Identify the same shopper across online, mobile, and in-store channels and share payment tokens between them.

View as MarkdownInstall skills

VINR uses a shopperReference — a stable, merchant-assigned identifier, typically the customer's email address or your internal user ID — to link payment methods, order history, and loyalty data across every channel you operate. Pass the same shopperReference whether the shopper is on your website, mobile app, or standing at a terminal, and VINR automatically unifies the record behind the scenes. No separate identity service is required.

shopperReferenceAsk

A shopperReference is the anchor for cross-channel identity. VINR stores it alongside each payment and each saved method, so the same token, history, and preferences follow the shopper wherever they transact.

Rules:

  • Must be unique per merchant — two different shoppers must never share a reference.
  • Must be stable across sessions — assign it once on account creation and never change it.
  • Must not change for a customer — reassignment will silently orphan their stored methods and history.

Pass shopperReference on every payment creation call, online and in-person.

import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const onlinePayment = await vinr.payments.create({
  amount: 3200,
  currency: 'EUR',
  shopperReference: 'user_8821',
  shopperEmail: 'ada@example.com',
  shopperName: 'Ada Lovelace',
  savePaymentMethod: true,
  returnUrl: 'https://yoursite.com/checkout/complete',
});

const terminalPayment = await vinr.terminal.payments.create({
  terminalId: 'term_01HZ5QXYZ',
  amount: 3200,
  currency: 'EUR',
  shopperReference: 'user_8821',
  shopperEmail: 'ada@example.com',
  reference: 'order_9104',
});

Prop

Type

If you already use Customers & stored methods, the shopperReference maps to your customer.id or a value you store in metadata. You do not need to migrate — pass shopperReference alongside customer and VINR links both records.

Shared payment tokensAsk

When a shopper saves a card during an online checkout (by passing savePaymentMethod: true), VINR vaults the method and associates the resulting pm_ token with the shopper's shopperReference. That same token is valid at any VINR terminal — present it directly on a terminal payment creation call. The shopper does not need to tap or insert their card.

Online: save a card

const onlineSave = await vinr.payments.create({
  amount: 1500,
  currency: 'GBP',
  shopperReference: 'user_8821',
  shopperEmail: 'ada@example.com',
  savePaymentMethod: true,
  returnUrl: 'https://yoursite.com/checkout/complete',
});

const savedToken = onlineSave.paymentMethod;

In-store: reuse the same token

const inStorePurchase = await vinr.terminal.payments.create({
  terminalId: 'term_01HZ5QXYZ',
  amount: 900,
  currency: 'GBP',
  shopperReference: 'user_8821',
  paymentMethod: savedToken,
  reference: 'order_9201',
});
const payment = await vinr.payments.create({
  amount: 2000,
  currency: 'USD',
  shopperReference: 'user_8821',
  savePaymentMethod: true,
  returnUrl: 'https://yoursite.com/checkout/complete',
});
const payment = await vinr.terminal.payments.create({
  terminalId: 'term_01HZ5QXYZ',
  amount: 2000,
  currency: 'USD',
  shopperReference: 'user_8821',
  paymentMethod: 'pm_4Rk9...',
  reference: 'pos_order_772',
});
const payment = await vinr.payments.create({
  amount: 2000,
  currency: 'USD',
  shopperReference: 'user_8821',
  paymentMethod: 'pm_4Rk9...',
  offSession: false,
  returnUrl: 'https://yourapp.com/checkout/complete',
});

Presenting a token at a terminal constitutes a card-on-file transaction. Ensure the shopper's consent to store and reuse their card was captured at the time of the original save. See Privacy and consent below.

Cross-channel order historyAsk

Retrieve all payments for a shopper — across online, in-person, and pay-by-link channels — by querying vinr.payments.list with the shopper's reference. Each payment in the response includes a channel field indicating where the transaction originated.

const history = await vinr.payments.list({
  shopperReference: 'user_8821',
  limit: 50,
});

for (const payment of history.data) {
  console.log(payment.id, payment.channel, payment.amount, payment.currency);
}

Prop

Type

The unified history is especially useful for customer service and dispute resolution. When a shopper calls about a transaction, look up shopperReference once and see every interaction regardless of channel, without querying separate systems.

Shopper recognition requires explicit consent. VINR links a shopper's identity across channels only when one of the following consent events has occurred: the shopper saved a card during checkout, opted into a loyalty programme, or created an account with your service. Passive browsing or guest checkout without explicit opt-in does not trigger cross-channel linkage.

GDPR and CCPA compliance — you must capture, store, and be able to demonstrate the legal basis for processing each shopper's cross-channel data. Record the consent event (type, timestamp, IP, consent text) in your own system and make it available on request. For shoppers in EEA or California, honour deletion requests within the statutory window. See Data privacy and GDPR for VINR's data processing commitments.

Capture consent at the earliest touchpoint — account creation, card save, or loyalty opt-in — and record the consent event in your system.

Pass shopperReference on payments only after consent has been granted. Omit it for guests who have not consented to cross-channel tracking.

If a shopper withdraws consent, call vinr.shoppers.delete to erase their profile and disassociate stored methods. See Shopper profile API below.

Shopper profile APIAsk

The shopper profile provides a single view of a recognised shopper: their identity fields, all associated payment methods, and their first-seen timestamp. Use it for customer service lookups, loyalty integrations, and right-to-erasure workflows.

Retrieve a profile

const shopper = await vinr.shoppers.retrieve('user_8821');

console.log(shopper.id);
console.log(shopper.paymentMethods);

Update a profile

const updated = await vinr.shoppers.update('user_8821', {
  email: 'ada.lovelace@example.com',
});

Delete a profile (right to erasure)

await vinr.shoppers.delete('user_8821');

Deleting a shopper profile disassociates all stored methods from the shopperReference and removes personal data held by VINR. Completed payment records are retained for regulatory purposes but are anonymised — shopperReference, shopperEmail, and shopperName are scrubbed.

Prop

Type

Next stepsAsk

Was this page helpful?
Edit on GitHub

Last updated on

On this page