Framework guides
The <powsoo-voice> custom element works in any environment. The embed snippet is the same everywhere — these are framework-specific placement notes.
Plain HTML
Paste directly before </body>:
<powsoo-voice widget-id="wid_abc123"></powsoo-voice><script> (() => { const d = document, s = d.createElement('script'); s.type = 'module'; s.src = 'https://w.powsoo.com/widget.js'; d.head.append(s); })();</script>React
Place the element in JSX. Guard the bootstrap script so it only runs once:
export function CallButton() { return ( <> {/* @ts-expect-error — custom element */} <powsoo-voice widget-id="wid_abc123" /> <script dangerouslySetInnerHTML={{ __html: `(() => { if (window.__powsooLoaded) return; window.__powsooLoaded = true; const d = document, s = d.createElement('script'); s.type = 'module'; s.src = 'https://w.powsoo.com/widget.js'; d.head.append(s); })();`, }} /> </> );}Add a global type declaration so TypeScript recognises the custom element:
declare namespace JSX { interface IntrinsicElements { 'powsoo-voice': React.DetailedHTMLProps< React.HTMLAttributes<HTMLElement> & { 'widget-id': string }, HTMLElement >; }}Next.js
Use Next.js’s <Script> component with strategy="lazyOnload" to avoid blocking the page:
import Script from 'next/script';
export function CallButton() { return ( <> {/* @ts-expect-error — custom element */} <powsoo-voice widget-id="wid_abc123" /> <Script id="powsoo-bootstrap" strategy="lazyOnload">{` (() => { const d = document, s = d.createElement('script'); s.type = 'module'; s.src = 'https://w.powsoo.com/widget.js'; d.head.append(s); })(); `}</Script> </> );}Vue / Nuxt
<template> <powsoo-voice widget-id="wid_abc123" /></template>
<script setup lang="ts">import { onMounted } from 'vue';
onMounted(() => { if (document.querySelector('script[src*="powsoo"]')) return; const s = document.createElement('script'); s.type = 'module'; s.src = 'https://w.powsoo.com/widget.js'; document.head.append(s);});</script>Add to vite.config.ts to suppress the unknown element warning:
vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('powsoo-'), }, },})Webflow
- In the Webflow designer, drag an Embed element to the page.
- Paste the full snippet (both the
<powsoo-voice>tag and the<script>block) into the embed. - Publish.
WordPress
Paste the snippet into Appearance → Theme file editor → footer.php just before </body>, or use a plugin that supports custom code injection (e.g. Insert Headers and Footers).
Squarespace
Go to Settings → Advanced → Code Injection → Footer and paste the snippet. It loads on every page.
Shopify
Add the snippet to your theme’s theme.liquid just before </body>.