Skip to main content
The ContextGPT JavaScript SDK lets you embed your chatbot on any website with a single <script> tag and control it programmatically using the $cgpt object.

Quick start

1

Get your chatbot ID

Find your chatbot ID in your dashboard under Installation.
2

Add the script

Paste this before the closing </body> tag:
<script
  type="module"
  src="https://widget.contextgpt.in/loader.js"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>
3

Test

Reload your page and click the chat bubble to test your chatbot.
Replace YOUR_CHATBOT_ID with your actual chatbot ID from the Installation page. The Installation page provides this snippet pre-filled with your ID.

Embed modes

The widget supports two modes controlled by data-* attributes on the script tag.
A chat bubble appears fixed in the bottom-right corner of the page. Clicking it opens the chat window.
<script
  type="module"
  src="https://widget.contextgpt.in/loader.js"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>
Add this once in your site-wide layout or footer template — it will appear on every page automatically.

Script tag attributes

AttributeRequiredDescription
data-chatbot-idYesYour unique chatbot ID
data-modeNoSet to "embedded" to use container mode. Omit for floating (default).
data-containerWhen data-mode="embedded"CSS selector for the container element (e.g. "#my-chat-container")
data-instanceNoA name for this widget instance. Required when loading multiple widgets on the same page (e.g. "floating", "sidebar").

URL parameters

Append these to the loader.js URL to modify widget behavior:
ParameterDescription
?hideButton=trueHides the floating bubble — widget is created but only openable via $cgpt commands
?hideWidget=trueSkips creating the floating widget entirely — use when you only want embedded containers
?instance=nameRequired when loading two script tags from the same source on the same page (e.g. ?instance=sidebar)
Example — hide the bubble and use a custom trigger button:
<button onclick="window.$cgpt.push(['open'])">Chat with us</button>

<script
  type="module"
  src="https://widget.contextgpt.in/loader.js?hideButton=true"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>

SDK methods reference

Control the widget programmatically using the $cgpt object. All commands use the push method:
window.$cgpt.push([command, ...args]);
Commands pushed before the widget finishes loading are buffered and replayed automatically — no need to wait for the script to load.
For a complete interactive reference with live testing, visit the SDK Methods page in your chatbot dashboard under Installation → SDK Advanced.

Widget visibility

Open the chat

window.$cgpt.push(['open']);
Example — open when a button is clicked:
document.getElementById('chat-btn').addEventListener('click', function () {
  window.$cgpt.push(['open']);
});

Open with a fresh conversation

Opens the chat and resets the current conversation in a single flicker-free step.
window.$cgpt.push(['open', { reset: true }]);
Prefer this over calling ['open'] then ['do', 'conversation:reset'] separately — it avoids a brief flash of the old conversation before the reset.

Close the chat

window.$cgpt.push(['close']);

Toggle the chat

Opens if closed, closes if open.
window.$cgpt.push(['toggle']);

Send messages

Send a message immediately

Sends a message on the user’s behalf. The widget opens automatically if it’s closed.
window.$cgpt.push(['do', 'message:send', 'What are your pricing plans?']);
Example — trigger on button click:
document.getElementById('pricing-btn').addEventListener('click', function () {
  window.$cgpt.push(['do', 'message:send', 'What are your pricing plans?']);
});

Prefill the message input

Fills the input field with text. The user can edit before sending. Widget opens automatically.
window.$cgpt.push(['set', 'message:text', "Hi! I'd like help with..."]);
Use message:send to send automatically without user interaction. Use message:text to suggest a message but let the user edit it first.

Manage conversations

Reset the conversation

Clears the conversation history and returns to the widget home page.
window.$cgpt.push(['do', 'conversation:reset']);
Example — “Start new chat” button:
document.getElementById('new-chat-btn').addEventListener('click', function () {
  window.$cgpt.push(['do', 'conversation:reset']);
});

Reload the widget

Completely tears down and reinitializes the widget. Useful after SPA route changes or when embedded containers appear dynamically.
window.$cgpt.push(['do', 'widget:reload']);
Example — reload on SPA route change:
router.on('routeChange', function () {
  setTimeout(function () {
    window.$cgpt.push(['do', 'widget:reload']);
  }, 100);
});

Chatbot context

Inject extra context around every message for more relevant, page-aware responses.
window.$cgpt.push(['set', 'context', ['prefix', 'suffix']]);
  • prefix — injected before the user’s message (custom persona, role)
  • suffix — injected after the user’s message (current page, URL)
Example — page-aware context:
window.$cgpt.push([
  'set',
  'context',
  [
    'You are a sales executive. Guide users to book a demo call.',
    'Current page: ' + document.title + '\nURL: ' + window.location.href,
  ],
]);
Context is injected transparently — users only see their original message in the chat UI.

User sessions

Automatically log users in using their verified email address. Requires a secure HMAC-SHA256 signature generated on your backend.
window.$cgpt.push([
  'set',
  'user:email',
  [
    'user@example.com',
    'cd7cc422ca57c82d...' // HMAC-SHA256 signature from your backend
  ]
]);
Never generate signatures in frontend code. Doing so exposes your API key and allows anyone to impersonate users. Always generate signatures on your backend server.
Backend example (Node.js):
const crypto = require('crypto');

const apiKey = process.env.CONTEXTGPT_API_KEY; // keep private

function signEmail(email) {
  return crypto.createHmac('sha256', apiKey).update(email).digest('hex');
}

// In your auth endpoint:
app.get('/api/chatbot-auth', (req, res) => {
  const userEmail = req.user.email;
  const signature = signEmail(userEmail);
  res.json({ email: userEmail, signature });
});
Frontend — fetch the signature and pass to widget:
fetch('/api/chatbot-auth')
  .then(res => res.json())
  .then(data => {
    window.$cgpt.push(['set', 'user:email', [data.email, data.signature]]);
  });

Custom CSS

Inject CSS into the widget’s shadow DOM to match your branding. The --cgpt-primary CSS variable is reactive and controls the bubble color, header, and user message bubbles.
window.$cgpt.push(['set', 'css', ':host { --cgpt-primary: #10b981; }']);
Calling this command again replaces the previous custom styles. Example — change font family:
window.$cgpt.push(['set', 'css', 'body { font-family: "Lato", sans-serif; }']);

Targeting multiple widgets

When you have more than one widget instance on the same page, use the targeting API to send commands to a specific instance.
TargetSyntaxScope
$cgpt.pushwindow.$cgpt.push([...])Broadcasts to all widgets on the page
$cgpt['instanceName']window.$cgpt['floating'].push([...])One specific widget by its data-instance name
$cgpt_widget['chatbotId']window.$cgpt_widget['uuid'].push([...])All instances sharing that chatbot ID
$cgpt_widget['chatbotId']['instanceName']window.$cgpt_widget['uuid']['floating'].push([...])One specific instance within a chatbot ID group
Example setup — floating + embedded on the same page:
<!-- Floating widget -->
<script
  type="module"
  src="https://widget.contextgpt.in/loader.js?instance=floating"
  data-chatbot-id="YOUR_CHATBOT_ID"
  data-instance="floating">
</script>

<!-- Embedded widget -->
<div id="chat-container" style="width: 100%; height: 600px;"></div>
<script
  type="module"
  src="https://widget.contextgpt.in/loader.js?instance=embedded"
  data-chatbot-id="YOUR_CHATBOT_ID"
  data-mode="embedded"
  data-container="#chat-container"
  data-instance="embedded">
</script>

<script>
  // Target only the floating widget
  window.$cgpt['floating'].push(['open']);

  // Target only the embedded widget
  window.$cgpt['embedded'].push(['set', 'message:text', 'Hello!']);

  // Broadcast to both
  window.$cgpt.push(['set', 'css', ':host { --cgpt-primary: #6366f1; }']);
</script>

Common use cases

Custom chat trigger (hide the bubble)

<button onclick="window.$cgpt.push(['open'])">Chat with us</button>

<script
  type="module"
  src="https://widget.contextgpt.in/loader.js?hideButton=true"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>

Page-aware context

<script>
  window.$cgpt = window.$cgpt || [];
  window.$cgpt.push([
    'set',
    'context',
    [
      'You are a helpful support agent.',
      'Page: ' + document.title + '\nURL: ' + window.location.href,
    ],
  ]);
</script>

<script
  type="module"
  src="https://widget.contextgpt.in/loader.js"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>

Pre-filled message on button click

<button id="pricing-btn">Ask about pricing</button>

<script>
  document.getElementById('pricing-btn').addEventListener('click', function () {
    window.$cgpt.push(['do', 'message:send', 'What are your pricing plans?']);
  });
</script>

Authenticated users (auto-login)

<script>
  fetch('/api/chatbot-auth')
    .then(res => res.json())
    .then(data => {
      window.$cgpt.push(['set', 'user:email', [data.email, data.signature]]);
    });
</script>

<script
  type="module"
  src="https://widget.contextgpt.in/loader.js"
  data-chatbot-id="YOUR_CHATBOT_ID">
</script>

Troubleshooting

Check the script tag
Ensure data-chatbot-id is correct and the script is present in the page source (View → Page Source).
Check browser console
Open DevTools (F12) and look for JavaScript errors.
Verify the chatbot has training data
A chatbot with no content will not appear.
Test in incognito mode
Rules out browser extensions or cached files causing the issue.
Commands are buffered automatically
You don’t need to wait for the script to load — push commands at any time and they replay once the widget is ready.
Check the object name
The SDK uses window.$cgpt, not window.$ContextGPT.
Check the syntax
All commands use the array form: window.$cgpt.push(['command', ...args]).
Check browser console
Look for any JavaScript errors that may prevent the widget from initializing.
Set an explicit height on the container
The widget fills 100% of its container’s dimensions. If the container has no height (e.g. height: auto), the widget will collapse. Set a fixed height: style="height: 600px".
Set overflow: hidden on the container
This prevents the widget’s internal scroll from escaping to the page.
Check the selector
Ensure data-container matches your container’s id or class exactly (e.g. "#my-chat-container").
Add data-instance to each script tag
Give each widget a unique instance name (e.g. data-instance="floating" and data-instance="sidebar").
Add ?instance=name to each script URL
Without the query string, the browser deduplicates module scripts with the same URL and only runs one.
Use ?hideWidget=true on the floating script
If you only want embedded containers and no floating bubble, add ?hideWidget=true to the floating script URL.
The widget uses a shadow DOM
Standard page CSS cannot reach inside the widget. Use $cgpt.push(['set', 'css', '...']) to inject styles.
Use :host for top-level variables
Set --cgpt-primary on :host { } to change the primary color reactively.
Calling the command again replaces previous styles
There is no merge — each set css call fully replaces the previous custom stylesheet.

Next steps

Installation guide

Platform-specific installation instructions

SDK Advanced

Full SDK method reference with live testing

Webhooks

Receive real-time chatbot events

API reference

Manage chatbots via the REST API