Skip to main content
This page covers the technical details of embedding the Web Chat Widget: pre-filling visitor data, Content Security Policy configuration, framework-specific setup, and the JavaScript API.
This is a developer-focused reference. For general setup, see the Widget Setup guide.

Pre-Filling Visitor Fields

If your website already knows the visitor’s name or email (e.g., from a login session), you can pre-fill the widget’s form fields and optionally lock them so the visitor cannot change them.

Via Data Attributes

Add attributes directly to the script tag:
<script
  src="https://ticketcord.net/api/webchat/widget.js"
  data-widget-key="WK_your_key_here"
  data-visitor-name="Jane Smith"
  data-visitor-email="jane@example.com"
  data-visitor-message="I need help with my order"
  data-lock-name="true"
  data-lock-email="true"
  defer
></script>
AttributeDescription
data-visitor-namePre-fill the name field
data-visitor-emailPre-fill the email field
data-visitor-messagePre-fill the first message
data-lock-nameSet to "true" to make the name field read-only
data-lock-emailSet to "true" to make the email field read-only
data-lock-messageSet to "true" to make the message field read-only
Lock fields when you trust the data. If the name and email come from your authenticated session, lock them to prevent visitors from impersonating other users. If the data is just a convenience default, leave them unlocked.

Via JavaScript API

For dynamic values (e.g., loaded after the page renders), set the window.TicketCordWidget object before the script loads, or at any point before the visitor opens the widget:
window.TicketCordWidget = {
  prefill: {
    name: 'Jane Smith',
    email: 'jane@example.com',
    message: 'I need help with my order',
    lockName: true,
    lockEmail: true,
    lockMessage: false
  }
}
The JavaScript API and data attributes can be used together. If both are present, the JavaScript API values take priority.

Content Security Policy (CSP)

If your website uses a Content-Security-Policy header, you need to allow the widget’s domain. Add the following directives:
script-src 'self' https://ticketcord.net;
connect-src 'self' https://ticketcord.net;
style-src 'self' 'unsafe-inline';
img-src 'self' https://ticketcord.net https://cdn.discordapp.com;

Directive Breakdown

DirectiveWhy It’s Needed
script-src https://ticketcord.netThe widget script itself
connect-src https://ticketcord.netAPI calls (config, session, messages) and the SSE stream
style-src 'unsafe-inline'The widget injects its own styles into a shadow DOM
img-src https://cdn.discordapp.comStaff avatar images from Discord
If you see Refused to load or Refused to connect errors in the console, your CSP is blocking the widget. Add the domains listed above to the relevant directives.

Next.js Example

If you’re using Next.js with a custom CSP in next.config.ts:
next.config.ts
const cspDirectives = [
  "default-src 'self'",
  "script-src 'self' https://ticketcord.net",
  "connect-src 'self' https://ticketcord.net",
  "style-src 'self' 'unsafe-inline'",
  "img-src 'self' https://ticketcord.net https://cdn.discordapp.com",
  // ... your other directives
]

const nextConfig = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: cspDirectives.join('; ')
          }
        ]
      }
    ]
  }
}

Image Domains

If your framework restricts which domains can serve images (e.g., Next.js images.remotePatterns), add both domains:
next.config.ts
const nextConfig = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'ticketcord.net' },
      { protocol: 'https', hostname: 'cdn.discordapp.com' },
    ]
  }
}

Framework-Specific Embedding

React / Next.js

Use the Script component with the afterInteractive strategy:
import Script from 'next/script'

export default function Layout({ children }) {
  return (
    <>
      {children}
      <Script
        src="https://ticketcord.net/api/webchat/widget.js"
        data-widget-key="WK_your_key_here"
        strategy="afterInteractive"
      />
    </>
  )
}
For dynamic pre-fill values from your auth context:
'use client'

import Script from 'next/script'
import { useSession } from 'next-auth/react'

export function ChatWidget() {
  const { data: session } = useSession()

  return (
    <Script
      src="https://ticketcord.net/api/webchat/widget.js"
      data-widget-key="WK_your_key_here"
      data-visitor-name={session?.user?.name ?? ''}
      data-visitor-email={session?.user?.email ?? ''}
      data-lock-name={session?.user?.name ? 'true' : 'false'}
      data-lock-email={session?.user?.email ? 'true' : 'false'}
      strategy="afterInteractive"
    />
  )
}

Vue / Nuxt

In your main layout or app.vue:
<template>
  <div>
    <NuxtPage />
  </div>
</template>

<script setup>
useHead({
  script: [
    {
      src: 'https://ticketcord.net/api/webchat/widget.js',
      'data-widget-key': 'WK_your_key_here',
      defer: true
    }
  ]
})
</script>

WordPress

Add this to your theme’s footer.php before the closing </body> tag, or use a plugin like “Insert Headers and Footers”:
<script
  src="https://ticketcord.net/api/webchat/widget.js"
  data-widget-key="WK_your_key_here"
  defer
></script>

Static HTML

Paste the snippet before </body> in every page where you want the widget:
<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
</head>
<body>
  <!-- Your page content -->

  <script
    src="https://ticketcord.net/api/webchat/widget.js"
    data-widget-key="WK_your_key_here"
    defer
  ></script>
</body>
</html>

Troubleshooting

Open your browser console (F12) and look for [TicketCord WebChat] messages:
  • Widget disabled: no allowed domains are configured — Add your domain to the allowed domains list in the dashboard.
  • Widget blocked: this domain is not in the allowed domains list — The current page’s origin doesn’t match any allowed domain. Check for typos (e.g., http vs https, www vs non-www).
  • Widget disabled: the bot owner's plan no longer includes web chat — The plan was downgraded. Upgrade back to Pro or Enterprise.
  • No console output at all — Verify the data-widget-key attribute is correct and the script URL is reachable.
Your Content Security Policy is blocking the widget. See the CSP section above for the required directives.
Add https://cdn.discordapp.com to your img-src CSP directive. Discord serves avatar images from this domain.
  • Ensure the data attributes are on the <script> tag itself, not on a parent element.
  • If using the JavaScript API, set window.TicketCordWidget before the script loads, or ensure the widget hasn’t already initialized.
  • Check that the pre-chat form is enabled in your dashboard settings — pre-fill values only appear on the form.
  • Check that the bot is online in your dashboard.
  • Verify the ticket category exists and the bot has permissions to create channels in it.
  • Look for rate limit errors in the console — the default is 10 messages per minute.

Need Help?

Get instant support via private DM