Implementation Examples
Real-world examples of SiteAssist widget integration
Overview
This guide provides complete, real-world examples of integrating the SiteAssist widget in various scenarios and platforms.
Basic Examples
Simple Website
The most straightforward integration for a basic website:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Website</title>
<!-- SiteAssist Widget -->
<script type="text/javascript">
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
</script>
<script type="text/javascript">
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
</script>
</head>
<body>
<h1>Welcome to My Website</h1>
<p>Your content here...</p>
</body>
</html>
Framework Examples
Next.js (App Router)
File: app/layout.tsx
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
{/* SiteAssist Widget Loader */}
<Script id="siteassist-loader" strategy="afterInteractive">
{`
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
`}
</Script>
{/* Initialize SiteAssist */}
<Script id="siteassist-init" strategy="afterInteractive">
{`
SiteAssist("init", {
apiKey: "${process.env.NEXT_PUBLIC_SITEASSIST_PUBLISHABLE_KEY}",
theme: "auto"
});
`}
</Script>
</body>
</html>
);
}
With environment variables:
# .env.local
NEXT_PUBLIC_SITEASSIST_PUBLISHABLE_KEY=pk_live_abc123
Next.js (Pages Router)
File: pages/_app.tsx
import type { AppProps } from "next/app";
import Script from "next/script";
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<Script id="siteassist-loader" strategy="afterInteractive">
{`
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
`}
</Script>
<Script id="siteassist-init" strategy="afterInteractive">
{`
SiteAssist("init", {
apiKey: "${process.env.NEXT_PUBLIC_SITEASSIST_PUBLISHABLE_KEY}",
theme: "auto"
});
`}
</Script>
</>
);
}
React
File: App.tsx
import { useEffect } from "react";
function App() {
useEffect(() => {
// Load SiteAssist script
if (!window.SiteAssist) {
const loader = document.createElement("script");
loader.innerHTML = `
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
`;
document.head.appendChild(loader);
// Initialize
const init = document.createElement("script");
init.innerHTML = `
SiteAssist("init", {
apiKey: "${import.meta.env.VITE_SITEASSIST_API_KEY}",
theme: "auto"
});
`;
document.head.appendChild(init);
}
}, []);
return <div className="App">{/* Your app content */}</div>;
}
export default App;
Alternative: Using public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React App</title>
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "%VITE_SITEASSIST_API_KEY%",
theme: "auto",
});
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>
Vue.js
File: index.html
or app.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue App</title>
<script>
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
SiteAssist("init", {
apiKey: import.meta.env.VITE_SITEASSIST_API_KEY,
theme: "auto"
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
Angular
File: src/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Angular App</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
</script>
</head>
<body>
<app-root></app-root>
<script>
// Initialize after Angular loads
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
</script>
</body>
</html>
Platform-Specific Examples
WordPress (Theme Integration)
File: header.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
<!-- SiteAssist Widget -->
<script type="text/javascript">
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
SiteAssist("init", {
apiKey: "<?php echo get_option('siteassist_api_key'); ?>",
theme: "auto"
});
</script>
</head>
Alternative: Using functions.php
<?php
function add_siteassist_widget() {
$api_key = get_option('siteassist_api_key');
if (empty($api_key)) return;
?>
<script type="text/javascript">
!function(t,e,c,n,s){if(t[s])return;const i=t[s]=function(){i._q.push(arguments)};i._q=[];const o=e.createElement("script");o.async=!0,o.src="https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js",e.head.appendChild(o)}(window,document,0,0,"SiteAssist");
SiteAssist("init", {
apiKey: "<?php echo esc_js($api_key); ?>",
theme: "auto"
});
</script>
<?php
}
add_action('wp_head', 'add_siteassist_widget');
?>
Advanced Use Cases
SaaS Dashboard with Sidepanel
Perfect for web applications and admin panels:
<!DOCTYPE html>
<html>
<head>
<title>SaaS Dashboard</title>
<style>
.app-wrapper {
display: flex;
min-height: 100vh;
}
.sidebar {
width: 250px;
background: #1a1a1a;
}
.main-content {
flex: 1;
padding: 2rem;
transition: margin-right 200ms ease-in-out;
}
</style>
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
type: "sidepanel",
theme: "auto",
appContainerSelector: ".main-content",
});
</script>
</head>
<body>
<div class="app-wrapper">
<aside class="sidebar">
<!-- Sidebar navigation -->
</aside>
<main class="main-content">
<!-- Main content - will be pushed when sidepanel opens -->
<h1>Dashboard</h1>
<p>Your content here...</p>
</main>
</div>
</body>
</html>
E-commerce with Custom Triggers
Product pages with custom "Ask AI" buttons:
<!DOCTYPE html>
<html>
<head>
<title>Product Page</title>
<style>
.sa-button {
display: none !important;
} /* Hide default button */
.product-help-btn {
background: #4f46e5;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 0.5rem;
cursor: pointer;
font-weight: 500;
}
</style>
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
</script>
</head>
<body>
<div class="product-page">
<h1>Premium Widget</h1>
<p class="price">$99.99</p>
<div class="product-description">
<p>This amazing product includes...</p>
</div>
<button class="product-help-btn" onclick="SiteAssist('open')">
💬 Ask AI about this product
</button>
<button class="add-to-cart" onclick="addToCart()">Add to Cart</button>
</div>
<script>
function addToCart() {
// Your add to cart logic here
console.log("Item added to cart");
}
</script>
</body>
</html>
Documentation Site with Content Selection
Perfect for documentation sites where you want to restrict text selection to main content areas:
<!DOCTYPE html>
<html>
<head>
<title>Documentation</title>
<style>
.sidebar {
width: 250px;
float: left;
padding: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
</style>
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
contentSelector: ".main-content", // Only show popover in main content
});
</script>
</head>
<body>
<div class="sidebar">
<nav>
<h3>Navigation</h3>
<ul>
<li><a href="/getting-started">Getting Started</a></li>
<li><a href="/api-reference">API Reference</a></li>
<li><a href="/examples">Examples</a></li>
</ul>
<!-- Text selection popover won't appear here -->
</nav>
</div>
<div class="main-content">
<h1>Getting Started</h1>
<p>
Welcome to our documentation. You can select any text in this area to
ask questions about it.
</p>
<p>
For example, select the text "API Reference" above and ask "What's in
the API reference?"
</p>
<!-- Text selection popover WILL appear here -->
</div>
</body>
</html>
E-commerce with Global Text Selection
Enable text selection everywhere for comprehensive product support:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
contentSelector: false, // Show popover everywhere
});
</script>
Blog with Article-Only Selection
Restrict text selection to article content only:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
contentSelector: "article .content", // Only in article content
});
</script>
Documentation Site with Auto-Open
Open widget automatically for users who seem stuck:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
// Track user behavior
let searchAttempts = 0;
// Count search attempts
document.querySelector(".search-input")?.addEventListener("input", () => {
searchAttempts++;
// If user searched 3+ times, offer help
if (searchAttempts >= 3 && !localStorage.getItem("help_offered")) {
setTimeout(() => {
SiteAssist("open");
localStorage.setItem("help_offered", "true");
}, 2000);
}
});
// If user stays for 60s without interaction, offer help
setTimeout(() => {
if (!localStorage.getItem("help_offered")) {
SiteAssist("open");
localStorage.setItem("help_offered", "true");
}
}, 60000);
</script>
Multi-Language Support
Sync widget theme with site language:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
// Detect user's language
const userLang = navigator.language || navigator.userLanguage;
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
// Log language for debugging
console.log("User language:", userLang);
</script>
A/B Testing Integration
Track which widget variant performs better:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
// A/B test: floating-bubble vs sidepanel
const variant = Math.random() < 0.5 ? "floating-bubble" : "sidepanel";
SiteAssist("init", {
apiKey: "pk_live_abc123",
type: variant,
theme: "auto",
...(variant === "sidepanel" && {
appContainerSelector: ".main-content",
}),
});
// Log which variant was shown
console.log("A/B test variant:", variant);
// Log engagement
window.addEventListener("sa:opened", () => {
console.log("Widget opened - variant:", variant);
});
</script>
Conditional Loading by Page
Load widget only on specific pages:
<script>
// Only load on pricing and product pages
const shouldLoadWidget =
window.location.pathname.startsWith("/pricing") ||
window.location.pathname.startsWith("/products/");
if (shouldLoadWidget) {
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
}
</script>
Custom Event Integration
Integrate with your analytics platform:
<script>
!(function (t, e, c, n, s) {
if (t[s]) return;
const i = (t[s] = function () {
i._q.push(arguments);
});
i._q = [];
const o = e.createElement("script");
((o.async = !0),
(o.src =
"https://cnrib24ur3hk4b49.public.blob.vercel-storage.com/widget/latest/widget.js"),
e.head.appendChild(o));
})(window, document, 0, 0, "SiteAssist");
SiteAssist("init", {
apiKey: "pk_live_abc123",
theme: "auto",
});
// Forward SiteAssist events to Google Analytics
window.addEventListener("sa:opened", () => {
// Send event to Google Analytics
if (typeof gtag !== "undefined") {
gtag("event", "chat_opened", {
event_category: "engagement",
event_label: "SiteAssist Widget",
});
}
});
window.addEventListener("sa:closed", () => {
// Send event to Google Analytics
if (typeof gtag !== "undefined") {
gtag("event", "chat_closed", {
event_category: "engagement",
event_label: "SiteAssist Widget",
});
}
});
// Forward to Segment
window.addEventListener("sa:opened", () => {
if (typeof analytics !== "undefined") {
analytics.track("Chat Opened", {
source: "siteassist",
page: window.location.pathname,
});
}
});
</script>
Next Steps
- API Reference - Complete API documentation
- Advanced Features - Explore powerful capabilities
- Configuration - Customization options
Need help implementing? Contact us at support@siteassist.io