Next.js
This guide covers installing the DAP SDK in Next.js applications using the App Router (Next.js 13+) or Pages Router (Next.js 12+).
Prerequisites
- Next.js 13+ (App Router) or Next.js 12+ (Pages Router)
App Router
Using next/script (Recommended)
Add the SDK to your root layout using the next/script component. Place two Script tags in app/layout.tsx: one for the SDK bundle and one for initialization.
import Script from 'next/script';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Script
id="breakground-dap-sdk"
src="https://cdn.example.com/sdk.js"
strategy="afterInteractive"
crossOrigin="anonymous"
/>
<Script id="breakground-dap-init" strategy="afterInteractive">
{`
window.DAPObject = 'DAP';
window.DAP = window.DAP || function() {
(window.DAP.q = window.DAP.q || []).push(arguments);
};
window.DAP.l = Date.now();
DAP('init', { tenantKey: 'YOUR_TENANT_KEY' });
`}
</Script>
</body>
</html>
);
}
Using a Client Component
Alternatively, create a 'use client' component with the dynamic injection pattern:
"use client";
import { useEffect } from "react";
let sdkBootstrapped = false;
export function BreakGroundSDK() {
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" });
}, []);
return null;
}
Then include <BreakGroundSDK /> in your root layout.
Pages Router
Using _document.tsx (Recommended)
Add the snippet to pages/_document.tsx inside the <Head> component:
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
<Html>
<Head>
<script
dangerouslySetInnerHTML={{
__html: `
(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' });
`,
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Using _app.tsx
Alternatively, initialize in pages/_app.tsx with useEffect:
import { useEffect } from 'react';
import type { AppProps } from 'next/app';
let sdkBootstrapped = false;
export default function App({ Component, pageProps }: AppProps) {
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() },
);
}
const 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' });
}, []);
return <Component {...pageProps} />;
}
TypeScript Support
Create a breakground.d.ts file in your project root:
declare global {
interface Window {
DAP: ((...args: unknown[]) => void) & { q?: unknown[][]; l?: number };
DAPObject: string;
}
}
export {};
Ensure the file is included in your tsconfig.json:
{
"include": ["breakground.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
Do not modify next-env.d.ts. Next.js regenerates this file automatically. Add your declarations in a separate file.
SPA Route Changes
Client-side navigation in Next.js (both App Router and Pages Router) is handled automatically by the SDK's pushState and popstate monitoring. No additional configuration is needed.
Gotchas
- Client-side only: All DAP code must run in the browser. Use
useEffector mark components with'use client'. Server Components and server-side code cannot accesswindow. - Script strategy: Use
strategy="afterInteractive"withnext/script. Do not use"beforeInteractive"as it can delay page hydration. - Middleware and Edge Functions: The SDK is a client-side library and cannot be used in Next.js middleware or edge functions.
- Environment variables: Use the
NEXT_PUBLIC_prefix for any values referenced in client-side code (e.g.,NEXT_PUBLIC_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