VA
Acceptance

Integration Examples

How to embed components in React, Vue, vanilla JS, and other frameworks.

Quick Integration

<!DOCTYPE html>
<html>
<head>
  <script src="https://sdk.embed.visa.com/acceptance/v1"></script>
</head>
<body>
  <div id="transactions" style="min-height: 600px;"></div>
  <script>
    VisaAcceptance.init({
      auth: { type: 'api-key', apiKey: 'YOUR_API_KEY' },
      locale: 'en-US',
      theme: { preset: 'anet', mode: 'light' },
    });
    VisaAcceptance.render('transactions', '#transactions');
  </script>
</body>
</html>
import { useEffect, useRef } from 'react';

export function EmbeddedTransactions({ apiKey }: { apiKey: string }) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current || typeof window.VisaAcceptance === 'undefined') return;

    VisaAcceptance.init({
      auth: { type: 'api-key', apiKey },
      theme: { preset: 'anet' },
    });

    const instance = VisaAcceptance.render('transactions', ref.current);
    return () => instance.destroy();
  }, [apiKey]);

  return <div ref={ref} className="min-h-[600px]" />;
}
<template>
  <div ref="container" style="min-height: 600px" />
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const props = defineProps({ apiKey: String });
const container = ref(null);
let instance = null;

onMounted(() => {
  if (!window.VisaAcceptance) return;

  VisaAcceptance.init({
    auth: { type: 'api-key', apiKey: props.apiKey },
  });

  instance = VisaAcceptance.render('transactions', container.value);
});

onUnmounted(() => {
  instance?.destroy();
});
</script>
'use client';
import { useEffect, useRef } from 'react';
import Script from 'next/script';

export default function TransactionsPage() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!ref.current || typeof window.VisaAcceptance === 'undefined') return;

    VisaAcceptance.init({
      auth: {
        type: 'oauth',
        getToken: () => fetch('/api/embed-token').then(r => r.json()).then(d => d.token),
      },
    });

    const instance = VisaAcceptance.render('transactions', ref.current);
    return () => instance.destroy();
  }, []);

  return (
    <>
      <Script
        src="https://sdk.embed.visa.com/acceptance/v1"
        strategy="beforeInteractive"
      />
      <div ref={ref} className="min-h-[600px]" />
    </>
  );
}

Best Practices

1. Initialize Once

Call init() once at app startup, not per component mount:

// app.ts — run once
VisaAcceptance.init({ auth: myAuth, theme: myTheme });

// components.ts — render as needed
VisaAcceptance.render('transactions', '#t');
VisaAcceptance.render('invoices', '#i');

2. Always Destroy on Unmount

Leaking instances causes memory issues and duplicate event listeners:

// React
useEffect(() => {
  const instance = VisaAcceptance.render('payment', ref.current);
  return () => instance.destroy(); // cleanup
}, []);

3. Handle Loading States

The component takes time to load. Show a skeleton while waiting:

VisaAcceptance.init({
  onEvent: (type) => {
    if (type === 'component_ready') hideSpinner();
    if (type === 'component_error') showError();
  },
});

4. Use OAuth for Production

Session auth is deprecated for cross-origin contexts. Use OAuth with a backend token exchange:

VisaAcceptance.init({
  auth: {
    type: 'oauth',
    getToken: async () => {
      const res = await fetch('/api/embed-token', { credentials: 'include' });
      const { token } = await res.json();
      return token;
    },
  },
});

Never expose raw API keys or secrets in client-side code for production. Use OAuth with a backend token exchange endpoint.

On this page