Skip to content
Documentation

Docs

Everything from "drop the snippet" to reading your first leads — plus signed webhooks for pushing leads into your own tools.

Installation

1. Install the snippet

Add this single line of JavaScript to your site's <head> tag.

<script src="https://clickmemaybe.com/cmm/YOUR_SITE_KEY.js" defer></script>

Replace YOUR_SITE_KEY with the site key from your Websites page — or just copy the ready-made snippet from the site's Manage page.

2. CMS-specific guides

There is no plugin to install — every platform below has a place to paste one line of HTML into <head>. Copy the snippet from your site's Manage page first.

WordPress

  1. Open Appearance → Theme File Editor (or use a free "Insert Headers and Footers" plugin — WPCode, or the one bundled with your theme).
  2. Paste the snippet into the Header / <head> scripts box and save.
  3. Purge any caching plugin (WP Rocket, LiteSpeed, W3TC) and reload your site.

Shopify

  1. In the admin go to Online Store → Themes → ⋯ → Edit code.
  2. Open layout/theme.liquid and paste the snippet right before </head>.
  3. Save. The widget loads on every storefront page; use page rules to limit it (e.g. /products/*).

Webflow

  1. Open Site settings → Custom code.
  2. Paste the snippet into Head code and save.
  3. Publish the site — custom code is only live after publishing.

Squarespace

  1. Go to Settings → Advanced → Code Injection (Business plan or higher).
  2. Paste the snippet into the Header field and save.
  3. Reload a public page; code injection is not shown in the editor preview.

Wix

  1. Open Settings → Custom code (requires a premium plan with a connected domain).
  2. Click Add custom code, paste the snippet, choose All pages and place it in Head.
  3. Apply and publish.

Custom HTML / SPA (React, Vue, Svelte, Next.js)

  1. Add the snippet to the <head> of your HTML template or index.html; for Next.js use next/script with strategy="afterInteractive".
  2. The loader is defer and self-contained — no npm package, no build step.
  3. Single-page apps: the widget reads the URL on each render, so page rules work after client-side navigation too.

3. Verify the script

Open your site, then come back to the dashboard. Your site card should show "Live" within 30 seconds.

Widgets

Create your first widget

Pick a category, drop in your headline and CTA, and pick which site to show it on. You can refine targeting and design later.

Widget types

  • Popup — popup live
  • Sticky Bar — sticky_bar live
  • Floating CTA — floating_cta live
  • Inline Form — form live
  • Exit Intent — exit_intent live
  • Countdown — countdown live
  • Social Proof — social_proof live
  • Announcement — announcement live
  • Callback — callback live
  • Slide-in — slide_in live
  • Welcome Mat — fullscreen live
  • Survey / NPS — survey live
  • Multi-step / Quiz — multi_step live
  • Age Gate — age_gate live
  • Video Popup — video_popup live
  • Cookie Consent — cookie_consent live
  • Sticky Add-to-cart — sticky_atc live
  • Back-in-stock — back_in_stock live
  • Live Visitors — live_visitors live
  • Spin-to-win — spin_to_win live
  • Reviews — reviews live
  • FAQ — faq live
  • Morph — morph soon

Design and brand

Each widget takes an accent color (button and highlights; the darker hover shade is derived automatically) and, on the callback widget, a screen position. Widgets inherit your page's font so they never look foreign. Brand fonts and a custom CSS escape hatch are on the roadmap; paid plans remove the "Powered by ClickMeMaybe" badge.

Targeting

Page rules

Show a widget only on selected paths (exact path such as /pricing, or a prefix such as /blog/*) and exclude paths where it must never appear. Exclusions win. Rules match the page path, not the query string.

Device

Target all devices, desktop only, or mobile only (viewports narrower than 768px). Geo, language, returning visitors, referrer and UTM targeting are on the roadmap.

Triggers

Each widget type has a built-in trigger: on-load popups appear shortly after the page is ready, exit-intent popups fire when the cursor leaves the viewport (timer + scroll-up on touch devices), bars and floating buttons render immediately. Scroll-depth, time-on-page and custom-event triggers are on the roadmap.

Analytics & Leads

Tracked events

We track impressions (widget rendered), clicks (interaction), and submissions (form completion). Custom events coming soon.

Working with leads

Leads land in your inbox in real time. Mark them new, reviewed, or contacted, and export as CSV anytime.

API & Integrations

REST API coming soon

List and create widgets, query analytics, and pull leads — all over a clean REST API.

Webhooks live

Get every new lead pushed to your own endpoint the moment it arrives. Open your website → Install → Security, paste an https:// URL and save. A signing secret is generated and shown once — store it.

Request

We send a POST with a JSON body and these headers:

Content-Type: application/json
X-CMM-Event: lead.created
X-CMM-Signature: sha256=<hex HMAC-SHA256 of the raw body, keyed with your secret>
User-Agent: ClickMeMaybe-Webhook/1.0

Payload — lead.created

{
  "event": "lead.created",
  "created_at": "2026-09-03T10:15:42+00:00",
  "lead": {
    "id": 1234,
    "email": "anna@example.com",
    "phone": null,
    "name": "Anna",
    "page": "https://yoursite.com/pricing",
    "device": "mobile",
    "type": "optin",
    "message": null,
    "score": null,
    "answers": null,
    "product": null,
    "prize": null,
    "code": null
  },
  "widget": { "id": 42, "name": "Exit popup — yoursite.com", "category": "exit_intent" },
  "website": { "id": 7, "domain": "yoursite.com" }
}

lead.type is one of callback, message, optin, contact, form, survey, quiz, back_in_stock, spin (falls back to the widget category). lead.message is the message or comment, lead.score the 0–10 NPS score (survey), lead.answers a list of {q, a} pairs from a quiz. lead.product is the product name from a back-in-stock form. lead.prize and lead.code are the spin-to-win segment and its coupon code. Fields that don't apply are null.

Delivery & retries

  • Respond with any 2xx within 5 seconds to acknowledge. Do the heavy work asynchronously.
  • Non-2xx responses, timeouts and connection errors are retried 3 times in total (after ~10 s, 60 s and 5 min). After that the delivery is marked failed.
  • Deliveries are sent from a queue — the visitor's widget never waits on your server.
  • Treat lead.id as the idempotency key: a retry may re-send the same lead.

Verifying the signature

Always compute the HMAC over the raw request body (before JSON parsing) and compare in constant time.

PHP
$secret   = getenv('CMM_WEBHOOK_SECRET');
$body     = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
$given    = $_SERVER['HTTP_X_CMM_SIGNATURE'] ?? '';

if (! hash_equals($expected, $given)) {
    http_response_code(401);
    exit('bad signature');
}

$event = json_decode($body, true);
// $event['lead']['email'] ...
http_response_code(204);
Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';

const app = express();
const SECRET = process.env.CMM_WEBHOOK_SECRET;

// Keep the raw body — the signature is computed over the exact bytes we sent.
app.post('/cmm-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
  const given = req.get('X-CMM-Signature') || '';

  if (expected.length !== given.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given))) {
    return res.status(401).send('bad signature');
  }

  const event = JSON.parse(req.body.toString('utf8'));
  // event.lead.email ...
  res.sendStatus(204);
});

Rotating the secret (Regenerate secret in Security) invalidates the old one immediately — update your endpoint first, then rotate.

Zapier, Make, n8n via webhook

No native app needed. In Zapier create a Zap with the trigger Webhooks by Zapier → Catch Hook, copy the generated URL and paste it as your webhook URL in Security. Send a test lead from your widget, then map lead.email, lead.name etc. into any of 5,000+ apps. The same works with Make (Custom webhook) and n8n (Webhook node).

Stop guessing. Start converting.

Install in 5 minutes. Publish your first widget today.

Start Free Now