Skip to main content
Show a loading overlay or spinner while the payment is being processed to provide feedback to users.

Recipe

checkout.addEventListener('primer:state-change', (event) => {
  const { isProcessing } = event.detail;

  if (isProcessing) {
    document.getElementById('loading-overlay').style.display = 'block';
  } else {
    document.getElementById('loading-overlay').style.display = 'none';
  }
});

How it works

  1. Listen for the primer:state-change event
  2. Check the isProcessing property from the event detail
  3. Show your loading UI when isProcessing is true
  4. Hide it when isProcessing is false

Variations

Custom loading screen

const overlay = document.getElementById('loading-overlay');

checkout.addEventListener('primer:state-change', (event) => {
  overlay.classList.toggle('visible', event.detail.isProcessing);
});
.loading-overlay {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s, visibility 0.2s;
}

.loading-overlay.visible {
  opacity: 1;
  visibility: visible;
}

Inline loading overlay

checkout.addEventListener('primer:state-change', (event) => {
  const { isProcessing } = event.detail;

  // Disable all inputs on the page during processing
  document.querySelectorAll('input, button, select').forEach((el) => {
    el.disabled = isProcessing;
  });
});

Show processing message

checkout.addEventListener('primer:state-change', (event) => {
  const statusEl = document.getElementById('status-message');

  if (event.detail.isProcessing) {
    statusEl.textContent = 'Processing your payment...';
    statusEl.className = 'status processing';
  } else if (event.detail.isSuccessful) {
    statusEl.textContent = 'Payment successful!';
    statusEl.className = 'status success';
  } else {
    statusEl.textContent = '';
    statusEl.className = 'status';
  }
});

See also

Disable external buttons

Prevent double submission during payment processing

Events guide

Handle payment lifecycle events