Frameworks
Idiomatic examples for React, Next.js, Vue, and plain HTML sites.
@coverport/js has no framework dependency. The examples below wrap mount() in whatever your framework uses for lifecycle, and clean up with destroy() on unmount.
React
import { useEffect, useRef } from 'react';
import coverport, { type CoverportSale } from '@coverport/js';
export function InsureButton({ product, onSale }: { product?: string; onSale: (s: CoverportSale) => void }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!ref.current) return;
const handle = coverport.mount(ref.current, {
key: process.env.NEXT_PUBLIC_COVERPORT_PK!,
product,
onComplete: onSale,
});
return () => handle.destroy();
}, [product, onSale]);
return <div ref={ref} />;
}Keep onSale stable with useCallback so the effect does not remount the button on every render.
Next.js (App Router)
The SDK touches window and document, so it must run on the client.
'use client';
import { useEffect, useRef } from 'react';
import coverport from '@coverport/js';
export default function InsureButton() {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const handle = coverport.mount(ref.current!, { key: process.env.NEXT_PUBLIC_COVERPORT_PK! });
return () => handle.destroy();
}, []);
return <div ref={ref} />;
}Publishable keys are safe in NEXT_PUBLIC_ variables. Secret API keys are not.
Vue 3
<script setup lang="ts">
import { onMounted, onBeforeUnmount, ref } from 'vue';
import coverport, { type CoverportHandle } from '@coverport/js';
const el = ref<HTMLElement | null>(null);
let handle: CoverportHandle | undefined;
onMounted(() => {
handle = coverport.mount(el.value!, {
key: import.meta.env.VITE_COVERPORT_PK,
onComplete: (sale) => console.log(sale.purchaseId),
});
});
onBeforeUnmount(() => handle?.destroy());
</script>
<template><div ref="el" /></template>Plain HTML, WordPress, Shopify, Webflow
Use the script tag. It auto-mounts every element with a data-coverport-key attribute and needs no build step.
<script src="https://unpkg.com/@coverport/js"></script>
<div data-coverport-key="pk_live_…" data-coverport-button-text="Insure this load"></div>For WordPress, paste both lines into a Custom HTML block. For Shopify, add the script to theme.liquid and the div wherever you want the button. For Webflow, use an Embed element.
Using your own button
If the mount target already contains markup, the SDK leaves it alone and only attaches a click handler:
<a id="insure-link" class="btn btn-outline">Add cargo insurance</a>
<script>
coverport.mount('#insure-link', { key: 'pk_live_…' });
</script>Opening from your own logic
Skip mount() entirely and call open() when it makes sense, for example after a shipment is booked:
async function bookShipment(form) {
const shipment = await api.createShipment(form);
coverport.open({
key: 'pk_live_…',
product: 'cargo-excess',
onComplete: (sale) => api.attachInsurance(shipment.id, sale.purchaseId),
});
}