@chamelioai/clickwrap-sdk
v0.1.0-beta.7
Published
Headless clickwrap consent SDK by Chamelio
Downloads
39
Readme
@chamelioai/clickwrap-sdk
A zero-dependency, headless TypeScript client for integrating Clickwraps securely into any web application.
Installation
This is a public npm package published under the @chamelioai scope.
npm install @chamelioai/clickwrap-sdkQuick Start with npm
import { ClickwrapClient } from '@chamelioai/clickwrap-sdk';
// Initialize client
const client = new ClickwrapClient({ publicKey: 'your_public_api_key' });
const slug = 'terms-of-service';
const userEmail = '[email protected]';
// Check if the user already accepted
const { accepted, clickwrapVersionId } = await client.status({ slug, userIdentifier: userEmail });
if (!accepted) {
// Fetch the agreement content (Markdown or HTML)
const terms = await client.get({ slug });
// terms.content — Markdown source
// terms.contentHtml — pre-rendered HTML
// terms.clickwrapType — "click_to_accept" or "scroll_and_accept"
// Record view after rendering the agreement to the user
await client.capture({
slug,
versionId: terms.clickwrapVersionId,
userIdentifier: userEmail,
eventType: 'viewed',
});
if (terms.clickwrapType === 'scroll_and_accept') {
// Record this after your agreement container reaches the bottom
await client.capture({
slug,
versionId: terms.clickwrapVersionId,
userIdentifier: userEmail,
eventType: 'scrolled_to_bottom',
});
}
// Record acceptance on click
await client.capture({
slug,
versionId: terms.clickwrapVersionId,
userIdentifier: userEmail,
eventType: 'accepted',
});
}Quick Start with a Script Tag
Use the browser global bundle for vanilla HTML integrations. The CDN should serve immutable versioned paths.
<script src="https://<cdn-domain>/clickwrap-sdk/<version>/clickwrap-sdk.global.min.js"></script>
<script>
const client = new window.Chamelio.ClickwrapClient({
publicKey: 'your_public_api_key',
});
</script>The global bundle exposes:
window.Chamelio.ClickwrapClient;
window.Chamelio.ClickwrapError;
window.Chamelio.ClickwrapNotFoundError;
window.Chamelio.InactiveVersionCaptureError;CDN usage with <script type="module"> is possible only with the ESM artifact. For vanilla HTML, use
clickwrap-sdk.global.min.js.
API
new ClickwrapClient(config)
| Option | Type | Required | Description |
| ----------- | -------- | -------- | ---------------------------------- |
| publicKey | string | Yes | Your organisation's public API key |
client.get({ slug })
Fetches the active clickwrap version for the given slug.
Returns: Promise<ClickwrapData>
| Field | Type | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------ |
| slug | string | The clickwrap slug |
| title | string | Display title |
| clickwrapType | string | click_to_accept or scroll_and_accept |
| content | string | Agreement content as Markdown |
| contentHtml | string | Agreement content as pre-rendered HTML — do not inject via innerHTML without sanitizing first. |
| clickwrapVersionId | number | Active version ID |
| versionNumber | number | Human-readable version number |
client.status({ slug, userIdentifier })
Checks whether a user has already accepted the clickwrap.
Returns: Promise<ClickwrapStatus>
client.capture({ slug, versionId, userIdentifier, eventType, metadata? })
Records a consent event.
| Param | Type | Required |
| ---------------- | ------------------------------------------------------------- | -------- |
| slug | string | Yes |
| versionId | number | Yes |
| userIdentifier | string | Yes |
| eventType | 'accepted' \| 'checked' \| 'viewed' \| 'scrolled_to_bottom' | Yes |
| metadata | Record<string, unknown> | No |
Returns: Promise<void>
Types
All types are exported and can be used in your own code:
import type {
CaptureParams,
ClickwrapData,
ClickwrapStatus,
ClickwrapType,
GetParams,
StatusParams,
} from '@chamelioai/clickwrap-sdk';Error Handling
import { ClickwrapError, ClickwrapNotFoundError, InactiveVersionCaptureError } from '@chamelioai/clickwrap-sdk';
try {
await client.get({ slug: 'unknown-slug' });
} catch (err) {
if (err instanceof ClickwrapNotFoundError) {
// 404 — slug not found or no active version
} else if (err instanceof InactiveVersionCaptureError) {
// 422 — attempted to capture against an inactive version
} else if (err instanceof ClickwrapError) {
// other API error — check err.status
}
}