React / Vite
This guide covers installing the DAP SDK in React applications built with Vite or Create React App (CRA).
Prerequisites
- React 18+
- Vite or Create React App
Option A — Static HTML (Recommended)
The simplest approach is adding the snippet directly to your HTML entry point. The SDK loads before React mounts, so it is ready by the time your components render.
Vite
Add the snippet to index.html in your project root, inside the <head> tag:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- DAP SDK Snippet -->
<script>
(function (w, d, s, o, f, js, fjs) {
w["DAPObject"] = f;
w[f] =
w[f] ||
function () {
(w[f].q = w[f].q || []).push(arguments);
};
w[f].l = 1 * new Date();
js = d.createElement(s);
fjs = d.getElementsByTagName(s)[0];
js.id = f;
js.src = o;
js.async = 1;
js.crossOrigin = "anonymous";
fjs.parentNode.insertBefore(js, fjs);
})(window, document, "script", "https://cdn.example.com/sdk.js", "DAP");
DAP("init", { tenantKey: "YOUR_TENANT_KEY" });
</script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Create React App
Add the same snippet to public/index.html inside the <head> tag:
<head>
<meta charset="utf-8" />
<!-- DAP SDK Snippet -->
<script>
(function (w, d, s, o, f, js, fjs) {
w["DAPObject"] = f;
w[f] =
w[f] ||
function () {
(w[f].q = w[f].q || []).push(arguments);
};
w[f].l = 1 * new Date();
js = d.createElement(s);
fjs = d.getElementsByTagName(s)[0];
js.id = f;
js.src = o;
js.async = 1;
js.crossOrigin = "anonymous";
fjs.parentNode.insertBefore(js, fjs);
})(window, document, "script", "https://cdn.example.com/sdk.js", "DAP");
DAP("init", { tenantKey: "YOUR_TENANT_KEY" });
</script>
</head>
Option B — Dynamic Injection
If you need to control when the SDK loads (for example, after user consent), inject it from a React component using useEffect.
React 18 StrictMode calls useEffect twice in development. A module-level guard prevents the SDK from being injected more than once.
import { useEffect } from "react";
let sdkBootstrapped = false;
useEffect(() => {
if (sdkBootstrapped) return;
sdkBootstrapped = true;
if (!window.DAP) {
window.DAPObject = "DAP";
const q: unknown[][] = [];
window.DAP = Object.assign(
(...args: unknown[]) => {
q.push(args);
},
{ q, l: Date.now() },
);
}
let script = document.getElementById(
"breakground-dap",
) as HTMLScriptElement | null;
if (!script) {
script = document.createElement("script");
script.id = "breakground-dap";
script.src = "https://cdn.example.com/sdk.js";
script.async = true;
script.crossOrigin = "anonymous";
document.head.appendChild(script);
}
window.DAP("init", { tenantKey: "YOUR_TENANT_KEY" });
window.DAP("on", "ready", () => console.log("SDK ready"));
}, []);
The sdkBootstrapped variable is declared outside the component at the module level. This ensures the guard persists across StrictMode re-mounts, which unmount and remount the component but re-execute the same module scope.
TypeScript Support
Add a type declaration so TypeScript recognizes window.DAP.
For Vite, add to src/vite-env.d.ts:
declare global {
interface Window {
DAP: ((...args: unknown[]) => void) & { q?: unknown[][]; l?: number };
DAPObject: string;
}
}
For CRA, add to src/react-app-env.d.ts:
declare global {
interface Window {
DAP: ((...args: unknown[]) => void) & { q?: unknown[][]; l?: number };
DAPObject: string;
}
}
SPA Route Changes
The SDK auto-detects URL changes by monitoring pushState and popstate events. Standard React Router navigation is handled automatically.
For application state changes that do not update the URL (for example, tabbed interfaces), manually notify the SDK:
DAP("refreshContent");
Gotchas
- StrictMode double-mount: Always use a module-level
let sdkBootstrapped = falseguard with dynamic injection. AuseRefinside the component resets on remount and will not prevent double initialization. - Do not remove the script tag in cleanup: The SDK manages its own lifecycle. Removing the script element from the DOM during an
useEffectcleanup causes issues. - Environment variables: Use the
VITE_prefix in Vite (import.meta.env.VITE_TENANT_KEY) and theREACT_APP_prefix in CRA (process.env.REACT_APP_TENANT_KEY).
Verification
- Open your application in a browser.
- Open the developer console (
F12orCmd+Option+I). - Type
window.DAPand press Enter. You should see the DAP function object. - Enable debug mode for detailed logs:
DAP("init", { tenantKey: "YOUR_TENANT_KEY", debug: true });
- Check the Console tab for messages prefixed with
[DAP]confirming successful initialization.
Next Steps
- SDK Configuration -- customize SDK behavior
- User Identity -- identify users for targeted content
- SDK Events -- listen to SDK lifecycle events