Skip to main content

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

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

warning
  • StrictMode double-mount: Always use a module-level let sdkBootstrapped = false guard with dynamic injection. A useRef inside 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 useEffect cleanup causes issues.
  • Environment variables: Use the VITE_ prefix in Vite (import.meta.env.VITE_TENANT_KEY) and the REACT_APP_ prefix in CRA (process.env.REACT_APP_TENANT_KEY).

Verification

  1. Open your application in a browser.
  2. Open the developer console (F12 or Cmd+Option+I).
  3. Type window.DAP and press Enter. You should see the DAP function object.
  4. Enable debug mode for detailed logs:
DAP("init", { tenantKey: "YOUR_TENANT_KEY", debug: true });
  1. Check the Console tab for messages prefixed with [DAP] confirming successful initialization.

Next Steps