Framework Guides
Install Callout in React, Next.js, Vue, or plain HTML.
Callout works with any web framework. The installation is always the same script tag — frameworks only matter for identity calls and milestone completion.
HTML / Static Sites
<script>
window.CalloutConfig = { projectId: "YOUR_PROJECT_ID" };
</script>
<script src="https://cdn.withcallout.com/widget.js" defer></script>That's it. Works with any static site, WordPress, or plain HTML.
React
Add the script tag to public/index.html. Use useEffect for identity:
import { useEffect } from "react";
import { useAuth } from "./auth";
function App() {
const { user } = useAuth();
useEffect(() => {
if (user && window.Callout) {
Callout.identify({
id: user.id,
email: user.email,
name: user.name
});
}
}, [user]);
return <div>{/* your app */}</div>;
}Next.js
Use next/script in your root layout:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Script id="callout-config" strategy="afterInteractive">
{`window.CalloutConfig = { projectId: "YOUR_PROJECT_ID" };`}
</Script>
<Script
src="https://cdn.withcallout.com/widget.js"
strategy="afterInteractive"
/>
</body>
</html>
);
}Vue
Add the script tag to index.html. Use onMounted for identity:
<script setup>
import { onMounted } from "vue";
import { useAuth } from "./composables/auth";
const { user } = useAuth();
onMounted(() => {
if (user.value && window.Callout) {
Callout.identify({
id: user.value.id,
email: user.value.email,
name: user.value.name
});
}
});
</script>Single-Page Apps
Callout automatically detects route changes in single-page apps. URL-targeted experiences (tours, tooltips, banners) re-evaluate on every navigation. You don't need to do anything special.
For conditional mounting (e.g., hide on admin pages):
router.on("routeChange", (route) => {
if (route.startsWith("/admin")) {
Callout.destroy();
} else {
Callout.init({ projectId: "YOUR_PROJECT_ID" });
}
});