CanWeChat
Docs

Install

Add the widget with one script tag and lock it to your domains.

Script tag

Paste this before the closing body tag. The script is async and isolates styles with Shadow DOM. It works on any site you control.

code
<script
  async
  src="https://canwechat.dev/api/widget.js"
  data-site="pk_live_...">
</script>

Next.js

Use next/script with afterInteractive so the widget does not block LCP. React stays in your app; the visitor widget is still vanilla.

code
import Script from "next/script";

export function CanWeChatWidget() {
  return (
    <Script
      src="https://canwechat.dev/api/widget.js"
      strategy="afterInteractive"
      data-site="pk_live_..."
    />
  );
}

React SPA

In a client-rendered React SPA (Vite, CRA, and similar), inject the same script once after mount. Prefer a single root-level effect or index.html tag so hot reloads do not load the widget twice. Call identify() or page() from your router after navigation if you track logged-in users or SPA route changes.

WordPress, Shopify, and Webflow

In WordPress, add the same script in footer.php (or a footer hook) before </body>. In Shopify, paste it in theme.liquid before </body>.

In Webflow, open Project Settings → Custom Code → Footer Code, paste the script tag with your site key, and publish. Custom code does not run in the Designer preview the same way as the published site, so verify on the live domain.

Identify from attributes

Optional data-user-id, data-name, and data-email feed the same identity pipeline as window.canwechat.identify(). Visitors can still chat without these.

code
<script
  async
  src="https://canwechat.dev/api/widget.js"
  data-site="pk_live_..."
  data-user-id="usr_123"
  data-name="Ada"
  data-email="ada@example.com">
</script>

Allowed domains

Lock the public key to hostnames you control. Add production domains such as example.com and docs.example.com on separate lines. Until you add a domain, any origin can load the key, which is useful for setup but not ideal for launch.

After saving allowed domains, test the widget from the exact production hostname. Local preview domains should not be added unless you intentionally want that key to work there.

Detection

The first successful widget config request marks the site as installed. The dashboard shows last widget load time.