Skip to main content

State management

Manage checkout state carefully to avoid re-initialization and stale data. Keep configuration objects stable and observe state changes with lifecycle-aware collectors.

Define options outside functions

Create options objects once and reuse them to avoid unnecessary re-initialization:
Define static options outside your function scope. The SDK uses deep comparison to detect actual changes, but stable object references reduce comparison overhead and improve performance.
// ✅ GOOD: Created once
const SDK_OPTIONS = {
  locale: 'en-GB',
};

function initCheckout() {
  const checkout = document.querySelector('primer-checkout');
  checkout.options = SDK_OPTIONS; // Same reference every time
}

// ❌ AVOID: Created every time function runs
function initCheckout() {
  const checkout = document.querySelector('primer-checkout');
  checkout.options = { locale: 'en-GB' }; // New object every execution
}
The SDK performs deep comparison to detect actual changes in the options object. Using stable references (the GOOD pattern above) minimizes comparison overhead and remains the recommended best practice for optimal performance.

Error handling

Log diagnostics IDs and handle failures gracefully. Every error from the SDK includes identifiers that help Primer support diagnose issues.

Monitor SDK initialization

checkout.addEventListener('primer:ready', (event) => {
  const primer = event.detail;
  console.log('SDK initialized');
  console.log('Applied locale:', checkout.options?.locale);
  console.log('Active payment methods:', primer.getPaymentMethods?.());
});

Debug configuration issues

Common debugging approaches for options-related issues:
When options aren’t working as expected, check these common issues first:
Check object reference stability:
const options = { locale: 'en-GB' };
console.log('Options reference:', options);

// Later in code
checkout.options = options;
console.log('Applied options:', checkout.options);
console.log('References match:', checkout.options === options);
Verify component properties vs SDK options:
// Component properties use setAttribute()
const checkout = document.querySelector('primer-checkout');

checkout.setAttribute('client-token', 'new-token');
console.log('Token attribute:', checkout.getAttribute('client-token'));

// SDK options use direct property assignment
checkout.options = { locale: 'en-GB' };
console.log('Options object:', checkout.options);

Performance

Minimize unnecessary re-renders and keep configuration stable. Initialize the SDK as early as possible so it can prefetch configuration while the user navigates.

Use TypeScript interfaces for type safety

Define TypeScript interfaces for your options objects to catch errors at compile time:
interface PrimerSDKOptions {
  locale: string;
  paymentMethodOptions?: {
    PAYMENT_CARD?: {
      requireCVV?: boolean;
      requireBillingAddress?: boolean;
    };
    APPLE_PAY?: {
      merchantName?: string;
      merchantCountryCode?: string;
    };
  };
}

const options: PrimerSDKOptions = {
  locale: 'en-GB',
  paymentMethodOptions: {
    PAYMENT_CARD: {
      requireCVV: true,
      requireBillingAddress: true,
    },
  },
};

Test options configuration separately

Create isolated tests for your options configuration:
describe('SDK Options Configuration', () => {
  it('should create valid options object', () => {
    const options = {
      locale: 'en-GB',
    };

    expect(options.locale).toBe('en-GB');
  });

  it('should maintain stable reference', () => {
    const options = { locale: 'en-GB' };
    const checkout = document.querySelector('primer-checkout');
    checkout.options = options;

    expect(checkout.options).toBe(options); // Same reference
  });
});

Security

Never expose API keys in client code. Keep configuration minimal and handle sensitive data on your server.

Distinguish between component properties and SDK options

Component Properties are HTML attributes that configure the component container. SDK Options are configuration settings for the SDK itself.
Mixing these up will cause silent failures. Component properties must use setAttribute(). SDK options must be assigned directly to .options.
Component Properties (use setAttribute()):
  • client-token - API authentication
  • custom-styles - Visual theming
  • loader-disabled - Loader behavior
SDK Options (use options object):
  • locale - UI language
  • Payment method configuration
  • Feature settings
  • Merchant domain and API settings
// ✅ CORRECT: Clear separation
const checkout = document.querySelector('primer-checkout');

// Component properties
checkout.setAttribute('client-token', 'your-token');
checkout.setAttribute('loader-disabled', 'false');

// SDK options
checkout.options = {
  locale: 'en-GB',
  applePay: { buttonType: 'buy' },
};

// ❌ WRONG: Mixing them up
checkout.setAttribute('locale', 'en-GB'); // Won't work - locale is an SDK option
checkout.options = {
  clientToken: 'your-token', // Wrong - this is a component property
};

Keep options simple and focused

Only configure what you need:
// ✅ GOOD: Simple, focused configuration
checkout.options = {
  locale: 'en-GB',
};

// ❌ AVOID: Over-configuration with unused options
checkout.options = {
  locale: 'en-GB',
  paymentMethodOptions: {
    PAYMENT_CARD: {
      requireCVV: true,
      requireBillingAddress: false,
      // ... 20 more unused options
    },
    APPLE_PAY: {
      // ... configured but not used
    },
  },
};

Testing

Use sandbox mode with test cards to verify your integration before going to production.
Test your checkout in a sandbox environment. Verify that:
  • Options are applied correctly
  • Events fire as expected
  • Error handling works for declined cards
  • All payment methods render properly