Documentation Index
Fetch the complete documentation index at: https://docs.getzenstep.com/llms.txt
Use this file to discover all available pages before exploring further.
Installation
Add the snippet to your root HTML file (public/index.html for Create React App, or the equivalent entry HTML for Vite).
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<div id="root"></div>
<!-- Add before </body> -->
<script
async
src="https://cdn.getzenstep.com/v1/snippet.js"
data-zenstep="YOUR_SNIPPET_KEY"
></script>
</body>
</html>
Calling identify
Call identify() inside a useEffect that runs when the authenticated user is available. The snippet’s queue system means this is safe to call before or after the script loads.
src/components/ZenstepProvider.tsx
import { useEffect } from "react";
import { useAuth } from "./your-auth-hook"; // replace with your auth provider
export function ZenstepProvider({ children }: { children: React.ReactNode }) {
const { user } = useAuth();
useEffect(() => {
if (!user) return;
window.zenstep?.identify(user.id, {
email: user.email,
plan: user.plan,
role: user.role,
createdAt: user.createdAt,
});
}, [user?.id]);
return <>{children}</>;
}
Wrap your app root with this provider:
import { ZenstepProvider } from "./components/ZenstepProvider";
ReactDOM.createRoot(document.getElementById("root")!).render(
<StrictMode>
<ZenstepProvider>
<App />
</ZenstepProvider>
</StrictMode>,
);
TypeScript types
Add a global type declaration so TypeScript knows about window.zenstep:
interface ZenstepAPI {
identify: (
userId: string,
attributes?: Record<string, string | number | boolean>,
) => void;
track: (event: string, data?: Record<string, unknown>) => void;
}
interface Window {
zenstep?: ZenstepAPI;
}
SPA navigation
Zenstep automatically detects client-side navigation using a History API pushState observer. When the URL changes, it re-evaluates all targeting rules and shows any newly-matching flows.
No additional setup is required.
Conditional loading (development)
If you want to disable Zenstep in your local development environment:
<!-- Only load in production -->
<script>
if (window.location.hostname !== "localhost") {
const s = document.createElement("script");
s.src = "https://cdn.getzenstep.com/v1/snippet.js";
s.dataset.zenstep = "YOUR_SNIPPET_KEY";
s.async = true;
document.body.appendChild(s);
}
</script>