Skip to main content
Install a live chat widget for support, sales qualification, or customer engagement. The pattern is the same for every major tool — paste a JavaScript snippet into your site’s layout.
Supported widgets: anything with a JavaScript snippet. Intercom, Crisp, Drift, Tidio, Tawk.to, Chatwoot, HubSpot Chat, Olark, LiveChat, Front — all work the same way.

Three Paths

Ask the project AI:
Add a Crisp chat widget to my site with website ID abc123.
Load it only in production, not in dev.
The AI finds your root layout, pastes the snippet in the right place, and adds a guard so the widget doesn’t load during development. Review and deploy.

The Generic Pattern

1

Sign up for the chat tool

Create an account with your chosen provider. Intercom, Crisp, Drift, etc. all have free or trial tiers.
2

Get your widget ID or script URL

Look in the provider’s dashboard under Settings > Install or Widget Code. They give you either a full <script> snippet or an ID you drop into a provided template.
3

Open your site's root layout

Depending on your stack:
  • Next.js App Router: app/layout.tsx
  • Next.js Pages Router: pages/_document.tsx
  • Static HTML: index.html
  • Other: whatever file wraps every page
4

Paste the snippet

Put it in the <head> or just before </body>. Most providers recommend before </body> because it doesn’t block initial render.
5

Deploy

Save and deploy. Visit your live site and confirm the widget bubble appears in the corner.

Example: Crisp

Paste this into your layout before </body>:
<script type="text/javascript">
  window.$crisp=[];
  window.CRISP_WEBSITE_ID="YOUR_CRISP_WEBSITE_ID";
  (function(){var d=document;var s=d.createElement("script");
  s.src="https://client.crisp.chat/l.js";s.async=1;
  d.getElementsByTagName("head")[0].appendChild(s);})();
</script>
Replace YOUR_CRISP_WEBSITE_ID with the ID from Crisp Dashboard > Website Settings > Setup Instructions.

Example: Intercom (React / Next.js)

Install the SDK:
npm install @intercom/messenger-js-sdk
Initialize it in your root layout:
'use client';
import { useEffect } from 'react';
import Intercom from '@intercom/messenger-js-sdk';

export function IntercomBoot({ user }: { user?: { id: string; email: string } }) {
  useEffect(() => {
    Intercom({
      app_id: process.env.NEXT_PUBLIC_INTERCOM_APP_ID!,
      user_id: user?.id,
      email: user?.email,
    });
  }, [user]);

  return null;
}
Mount <IntercomBoot user={currentUser} /> once in your layout. If the user is logged out, leave user undefined and Intercom runs in anonymous mode.

Example: Tawk.to (Free, Simple)

Before </body>:
<script type="text/javascript">
  var Tawk_API=Tawk_API||{}, Tawk_LoadStart=new Date();
  (function(){
    var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
    s1.async=true;
    s1.src='https://embed.tawk.to/YOUR_TAWK_ID/default';
    s1.charset='UTF-8';
    s1.setAttribute('crossorigin','*');
    s0.parentNode.insertBefore(s1,s0);
  })();
</script>
Most chat widgets drop tracking cookies and fall under GDPR/ePrivacy. If you’ve enabled cookie consent (see Site Enhancements), gate the widget script until the user consents to functional or analytics cookies.
Basic gating pattern:
if (cookieConsent.functional) {
  loadChatWidget();
}
Or wrap the <script> tag and only inject after consent. Your consent library (OneTrust, Cookiebot, or built-in) will have an event to hook into.

Performance Tips

Chat widgets typically add 50–200 KB of JS. To avoid slowing down first paint:
  • Load with async or defer — most provider snippets already do this
  • Place script before </body> rather than in <head>
  • Lazy-load after idle — for aggressive optimization, wrap the init in requestIdleCallback
  • Don’t load on all pages — skip the widget on high-traffic SEO pages if support isn’t offered there
Example lazy-load:
if ('requestIdleCallback' in window) {
  requestIdleCallback(loadChatWidget);
} else {
  setTimeout(loadChatWidget, 2000);
}

Customization

Most providers let you customize in their dashboard (no code):
  • Bubble color and position
  • Greeting messages based on page or user segment
  • Operating hours (automatic “we’re offline” messages)
  • Pre-chat survey (name, email, reason for contact)
  • Avatar and operator names
Spend 10 minutes in the provider dashboard before writing custom code — you probably don’t need to.

Using hiveku.json Build Env (Advanced)

For Next.js projects with per-environment widget IDs:
1

Set env vars

In Project > Settings > Environment Variables, add NEXT_PUBLIC_CHAT_WIDGET_ID per environment (dev, staging, production).
2

Render conditionally

{process.env.NEXT_PUBLIC_CHAT_WIDGET_ID && (
  <ChatWidget id={process.env.NEXT_PUBLIC_CHAT_WIDGET_ID} />
)}
Leave staging’s var blank to disable chat there.
3

Deploy

Redeploy each environment separately after setting its var.

Test It

1

Deploy to production

Chat widgets rarely work in local dev due to provider allow-lists. Deploy to your Hiveku URL or custom domain.
2

Open the live site

The chat bubble should appear in the corner (typically bottom-right).
3

Open the chat

Click the bubble. A chat window should open. Type a test message.
4

Verify on the provider dashboard

Log in to your chat provider. The test message should appear in their inbox or conversations view.

Troubleshooting

Open the browser DevTools console on your live site. If there’s a script error (typo in the snippet, wrong ID, blocked by CSP), it’ll show there. Also check Network tab for the widget script URL — if it’s blocked or 404ing, the snippet or ID is wrong.
Usually an ad blocker or corporate firewall blocking the provider’s server. Try in an incognito window with extensions disabled. If it works there, document the fix — affected visitors can whitelist the domain.
The script got added twice — commonly once in the root layout and once in a per-page file (or via a plugin and manually). Remove one. Browser DevTools > Elements can help you find duplicate <script> tags.
Move the script from <head> to just before </body>, and make sure it uses async or defer. If you need aggressive optimization, lazy-load the widget with requestIdleCallback or a 2–3 second delay — the user won’t miss a widget they can’t see yet.

What’s Next?

Site Enhancements

Enable cookie consent and other site-wide features

Environment Variables

Store widget IDs per environment

CRM Contacts

Sync chat leads into your CRM