Installation
Install method 3: Custom Trigger (SDK mode)
Headless mode. No teaser is rendered — you wire up your own button and call window.ShareCount.open() to launch the dialog.
Custom Trigger mode renders no teaser. The embed loads silently, waits for you to call window.ShareCount.open(), and launches the share-to-earn dialog over your page. Use this when the entry point belongs inside your own UI — a hero CTA, an in-app menu, a settings tile.
1. Put ShareCount in Custom Trigger mode
From the dashboard: Appearance → Display mode → Custom Trigger (SDK). Save. Nothing else in your campaign changes — only the teaser disappears.
2. Mount the embed once per page
You still need the two-line snippet on the page. The <div data-sharecount=…> is the mount node; the script loads window.ShareCount onto the page.
<!-- ShareCount widget (Custom Trigger / SDK mode) -->
<div data-sharecount="YOUR_PUBLIC_KEY"></div>
<script async src="https://www.sharecount.app/embed.js"></script>
<!-- Anywhere in your page, your own button: -->
<button id="share-and-earn">Share & earn a coupon</button>
<script>
document.getElementById("share-and-earn").addEventListener("click", function () {
// Opens the share-to-earn dialog over your page.
window.ShareCount && window.ShareCount.open && window.ShareCount.open();
});
</script>3. Wire it to anything you want
Any element that can receive a click can open the dialog. A button is the friendliest, but you can also wire links, images, menu items, or a keyboard shortcut.
React / Next.js
// React example — Custom Trigger mode
// 1. Render the mount node + loader once (e.g. in a layout).
// The src is async; the embed scans the DOM and re-scans on mutations.
"use client";
import Script from "next/script";
export function ShareCountMount({ publicKey }: { publicKey: string }) {
return (
<>
<div data-sharecount={publicKey} />
<Script src="https://www.sharecount.app/embed.js" strategy="afterInteractive" />
</>
);
}
// 2. Anywhere in your tree:
function ShareCTA() {
return (
<button
onClick={() => (window as any).ShareCount?.open?.()}
>
Share & earn a coupon
</button>
);
}What the SDK exposes
window.ShareCount.open(publicKey?)— opens the dialog. With no argument, it uses the first[data-sharecount]element on the page; pass a key explicitly to open a specific product’s widget.window.ShareCount.close()— closes the dialog if it’s open.
4. Detect when the script is ready
Because the script is async, your code can run before it’s loaded. The dialog will silently no-op if window.ShareCountisn’t there yet. Guard your handler:
function openShareDialog() {
if (window.ShareCount && window.ShareCount.open) {
window.ShareCount.open();
return;
}
// Try again next tick — the script is still loading.
setTimeout(openShareDialog, 100);
}Single page apps just work
The embed watches the DOM for added [data-sharecount] nodes, so SPA route changes don’t need re-init. The dialog itself is mounted once into the body, behind a Shadow DOM, and survives navigations.
Common patterns
Open from an “Earn a coupon” menu item
<li>
<a href="#" onclick="window.ShareCount.open(); return false;">
Share & earn a coupon
</a>
</li>Open after a delay (post-signup nudge)
// 8 seconds after a successful signup, invite them to share.
setTimeout(() => window.ShareCount?.open?.(), 8000);Keyboard shortcut
document.addEventListener("keydown", (e) => {
if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
window.ShareCount?.open?.();
}
});Content-Security-Policy
If your site sends a strict CSP, allow the embed origin and the iframe source:
# Content-Security-Policy headers you'll need
script-src 'self' https://www.sharecount.app
frame-src https://www.sharecount.app
connect-src 'self' https://www.sharecount.app
img-src 'self' data: https:
style-src 'self' 'unsafe-inline' # the embed sets a small amount of inline CSSMultiple products on one page
Render one [data-sharecount] per product. Pass the specific key to open() when triggering. The dialog iframes are cached per key after first load.
For agent installs, see Installing with an AI agent.