Quick Start
NorthLoop lets you add a live video calling widget to any website with a single script tag. Visitors submit their details and connect instantly with your sales team — no downloads, no scheduling, no friction.
Installation
Paste the following snippet into the <head> of your HTML. Replace YOUR_API_KEY with the key from your NorthLoop portal.
<!-- NorthLoop Widget -->
<script
src="https://northloop.io/widget.js"
data-key="YOUR_API_KEY"
data-team="sales"
async>
</script>The script loads asynchronously — it has zero impact on your page's Core Web Vitals. The widget appears as a floating button in the bottom-right corner by default.
Your First Call
Once the script is installed, here is what happens end-to-end:
- 1Visitor clicks the widget button and fills in their name and company.
- 2NorthLoop sends a push notification to all online agents in the specified team.
- 3An agent taps "Answer" in the web dashboard or mobile app.
- 4Both parties are connected via HD WebRTC video in under 3 seconds.
- 5After the call, a webhook fires to your configured endpoint with full call metadata.
Configuration
Customise the widget's behaviour and appearance using HTML data attributes on the script tag, or at runtime via the JavaScript API.
Script Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
data-keyrequired | string | — | Your NorthLoop API key. Found in Portal → Widgets. |
data-team | string | "default" | Slug of the agent team that receives incoming calls from this widget. Create teams in Portal → Team. |
data-color | hex string | "#2563EB" | Primary brand colour applied to the widget button and call-to-action elements. Accepts any valid CSS hex colour. |
data-position | "bottom-right" | "bottom-left" | "bottom-right" | Corner of the viewport where the widget button is anchored. |
data-title | string | "Talk to our team" | Label shown on the widget button and at the top of the call form. |
data-offline-message | string | "Leave us a message" | Text displayed on the widget when no agents are available. Clicking it opens the offline contact form. |
data-collect-email | "true" | "false" | "false" | When true, an optional email field is added to the pre-call form for lead capture. |
data-locale | BCP-47 string | "en" | Language code for widget UI strings. Built-in support for "en", "fr", "de", "es", "pt", "ja". Custom locales can be provided via the JS API. |
JavaScript API
After the script loads, a global window.NorthLoop object is available for programmatic control.
// Open the call form programmatically (e.g. from your own CTA button)
window.NorthLoop.open();
// Close the widget panel without ending an active call
window.NorthLoop.close();
// Completely remove the widget from the DOM
window.NorthLoop.destroy();
// Pre-fill visitor fields to reduce form friction
window.NorthLoop.prefill({
name: "Jane Smith",
company: "Acme Corp",
email: "[email protected]",
});
// Listen for widget lifecycle events
window.NorthLoop.on("call:connected", (data) => {
console.log("Call connected:", data.callId);
});
window.NorthLoop.on("call:ended", (data) => {
console.log("Duration:", data.durationSeconds, "s");
});CSS Customization
The widget renders inside a Shadow DOM, so global stylesheets do not bleed in. Use the data-color attribute for brand colours. For advanced overrides, inject a CSS string at initialisation:
window.NorthLoop.configure({
customCSS: `
.nl-button { border-radius: 8px; }
.nl-form-card { font-family: "Inter", sans-serif; }
`,
});Webhooks
NorthLoop sends an HTTP POST to your endpoint for every call lifecycle event. Webhooks are ideal for syncing calls to your CRM, triggering follow-up automations, or logging to your data warehouse.
Setup
Register your endpoint in Portal → Settings → Webhooks. You can register up to 5 endpoints per organisation. Each endpoint receives all events; use the event field to filter in your handler.
import crypto from "crypto";
export async function POST(req) {
const rawBody = await req.text();
const signature = req.headers.get("x-northloop-signature");
// Verify the request came from NorthLoop (see Verifying Signatures)
const expected = crypto
.createHmac("sha256", process.env.NORTHLOOP_WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
if (signature !== `sha256=${expected}`) {
return new Response("Unauthorized", { status: 401 });
}
const event = JSON.parse(rawBody);
switch (event.type) {
case "call.answered":
await syncCallToCRM(event.data);
break;
case "call.ended":
await logCallDuration(event.data);
break;
}
return new Response("OK", { status: 200 });
}Events Reference
Click any event to expand its full payload schema.
Verifying Signatures
Every webhook request includes an X-NorthLoop-Signature header. The value is an HMAC-SHA256 digest of the raw request body, prefixed with sha256=. Your webhook secret is available in Portal → Settings → Webhooks.
import hmac, hashlib
def verify_signature(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(),
raw_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)Examples
Common integration patterns for popular frameworks and platforms.
React / Next.js
Load the widget script once in your root layout using a useEffect. This ensures it mounts after hydration and is not duplicated across route changes.
"use client";
import { useEffect } from "react";
export default function RootLayout({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (document.querySelector('script[data-northloop]')) return;
const script = document.createElement("script");
script.src = "https://northloop.io/widget.js";
script.setAttribute("data-key", process.env.NEXT_PUBLIC_NORTHLOOP_KEY!);
script.setAttribute("data-team", "sales");
script.setAttribute("data-northloop", "true");
script.async = true;
document.head.appendChild(script);
}, []);
return <html><body>{children}</body></html>;
}WordPress
Add the following snippet to your theme's functions.php, or paste the HTML directly into a Custom HTML block in the site editor.
add_action('wp_head', function () {
echo '<script
src="https://northloop.io/widget.js"
data-key="YOUR_API_KEY"
data-team="sales"
async>
</script>';
});Shopify
In your Shopify admin, go to Online Store → Themes → Edit code. Open layout/theme.liquid and paste the snippet just before the closing </head> tag.
<!-- NorthLoop Widget -->
<script
src="https://northloop.io/widget.js"
data-key="{{ settings.northloop_api_key }}"
data-team="sales"
data-color="{{ settings.northloop_color | default: '#2563EB' }}"
async>
</script>Store your API key in Theme Settings so it is not hard-coded in the template. Add a northloop_api_key text field to your config/settings_schema.json.
