Skip to Content
The AKIN Travel developer platform is in beta — APIs may change. Get started →
React SDKEmbed widget

Embed widget (<script> + Web Components)

The embed widget is the framework-agnostic way to add Akin loyalty + auth to any site — Vue, Angular, Svelte, plain HTML, or a server-rendered stack. It ships as Web Components  over @akin-travel/sdk-core, so you integrate with a single <script> tag and a few custom elements. No framework lock-in, no build step.

Using React? The React SDK (providers + hooks + headless components) is the better fit. Reach for the embed widget for everything else.

Quickstart

Add the script and drop in the elements:

Use a publishable key. data-api-key sits in your page source, so it must be a publishable (browser-safe) key — read-only by construction. Never put a secret (server) key here. See publishable vs secret keys.

<script src="https://cdn.jsdelivr.net/npm/@akin-travel/sdk-embed/dist/akin-embed.global.js" data-partner-id="YOUR_PARTNER_ID" data-api-key="YOUR_PUBLISHABLE_PARTNER_API_KEY" data-environment="production" data-firebase-api-key="…" data-firebase-auth-domain="…" data-firebase-project-id="…" data-firebase-app-id="…" data-verify-callback-url="https://your-site.example/loyalty"></script> <akin-login></akin-login> <akin-loyalty-card></akin-loyalty-card> <akin-tier-progress data-tiers='[{"displayName":"Silver","points":1000},{"displayName":"Gold","points":5000}]'></akin-tier-progress>

That’s it. The script auto-initialises from its own data-* attributes, registers the custom elements, and (if the page is the magic-link landing) completes the pending sign-in from the URL token. A member signs in via <akin-login>, and the loyalty widgets render their tier and points.

The elements

TagWhat it renders
<akin-login>Magic-link email form, plus passkey and Google sign-in when available; a signed-in summary with sign-out once authenticated
<akin-loyalty-card>The member’s AKIN points, spendable balance, and tier badge
<akin-tier-progress>The current tier and a progress bar toward the next one

<akin-tier-progress> needs the tier ladder to draw a bar — pass it as data-tiers (JSON, sorted or unsorted):

<akin-tier-progress data-tiers='[{"displayName":"Silver","points":1000},{"displayName":"Gold","points":5000},{"displayName":"Platinum","points":15000}]'></akin-tier-progress>

Configuration (data-* attributes)

Set these on the <script> tag (auto-init) or pass the camelCase equivalents to AkinEmbed.init({...}).

AttributeRequiredDescription
data-partner-idYour partner UUID
data-api-keyYour partner API key (pk_…)
data-environmentproduction (default), staging, or development
data-api-urlOverride the GraphQL endpoint (defaults per environment)
data-verify-callback-urlWhere magic-link / signup emails return the member
data-gip-tenant-idGIP tenant id (multi-tenancy)
data-firebase-api-keyauthFirebase/GIP web config
data-firebase-auth-domainauthFirebase/GIP web config
data-firebase-project-idauthFirebase/GIP web config
data-firebase-app-idauthFirebase/GIP web config
data-debugVerbose console logging
data-auto-initfalse to skip auto-init and call AkinEmbed.init(...) yourself

The four data-firebase-* fields are required for sign-in (magic link, passkey, Google all run through Firebase/GIP). Without them the widgets render but auth is disabled.

Theming

CSS custom properties inherit through the Shadow DOM boundary, so the widgets honour the same partner token contract as white-label automatically. Set the namespaced --akin-* tokens, or expose the white-label tokens (--primary, --background, --foreground, --secondary, --muted, --border, --radius) — the widgets fall back to them, then to neutral defaults. OKLCH, hex, and rgb values all pass through verbatim.

:root { --akin-primary: oklch(0.62 0.19 28); --akin-radius: 0.75rem; --akin-font: 'Inter', system-ui, sans-serif; }

Per-widget override with data-theme (JSON):

<akin-loyalty-card data-theme='{"primary":"#0f766e","radius":"1rem"}'></akin-loyalty-card>

Because everything renders inside an open Shadow DOM, host-page CSS can’t leak into the widgets and the widgets’ CSS can’t leak out.

Events

The elements emit composed CustomEvents that cross the Shadow DOM boundary:

document.querySelector('akin-login') .addEventListener('akin:authenticated', (e) => { console.log('signed in', e.detail.member); });

akin:magic-link-sent, akin:authenticated, akin:signed-out, akin:error.

Framework mount snippets

The elements are standard custom elements — they work in any framework. A couple need a one-line hint so the framework doesn’t try to resolve <akin-*> as its own component.

Vue

// vite.config.ts import vue from '@vitejs/plugin-vue'; export default { plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('akin-'), } } })], };
<template> <akin-login /> <akin-loyalty-card /> </template>

Angular

import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule {}
<akin-login></akin-login> <akin-loyalty-card></akin-loyalty-card>

Svelte

No configuration needed — use the tags directly:

<akin-login /> <akin-loyalty-card />

npm install (bundler integration)

If you’d rather bundle the widgets with your app than load the CDN script:

npm install @akin-travel/sdk-embed @akin-travel/sdk-core
import { createAkinEmbed } from '@akin-travel/sdk-embed'; createAkinEmbed({ partnerId: 'YOUR_PARTNER_ID', apiKey: 'YOUR_PARTNER_API_KEY', environment: 'production', firebaseApiKey: '…', firebaseAuthDomain: '…', firebaseProjectId: '…', firebaseAppId: '…', verifyCallbackUrl: 'https://your-site.example/loyalty', });

createAkinEmbed returns the controller for programmatic use (requestMagicLink, signInWithPasskey, signInWithGoogle, signOut, subscribe), and the elements bind to it automatically.

Troubleshooting: Failed to fetch on staging

If a staging integration throws Failed to fetch / a CORS preflight error in the browser console, your bundle predates the 2026-06 staging endpoint move. Staging migrated off the raw Cloud Run URL onto the branded proxy https://staging-api.akintravel.com/graphql; only the branded host passes the API’s CORS allowlist. Two fixes:

  • Upgrade to the latest @akin-travel/sdk-embed + @akin-travel/sdk-core (the corrected default ships in sdk-core0.1.1), or

  • Override immediately without upgrading — point the endpoint at the branded host:

    <script data-environment="staging" data-api-url="https://staging-api.akintravel.com/graphql"></script>

    or, via the programmatic API, createAkinEmbed({ …, apiUrl: 'https://staging-api.akintravel.com/graphql' }).

Versioning & platform notes

The embed widget is the recommended path for non-React frameworks, including Vue — see Platform support. It follows the SDK versioning & release policy.

Last updated on