React / Next.js Integration
Integration guide for React and Next.js applications.
Next.js (App Router - Recommended)
Method 1: Script in layout.tsx
// app/layout.tsx
import Script from 'next/script'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{children}
{/* Ad Sentinelle SDK */}
<Script
src="https://adwall-backend-xxxxx.run.app/v1/loader/YOUR_SITE_ID.js"
strategy="afterInteractive"
/>
</body>
</html>
)
}
Method 2: Dedicated Component
Create a reusable component:
// components/AdSentinelle.tsx
'use client'
import { useEffect } from 'react'
interface AdSentinelleProps {
siteId: string
debug?: boolean
}
export function AdSentinelle({ siteId, debug = false }: AdSentinelleProps) {
useEffect(() => {
// Optional configuration
if (debug) {
(window as any).ADWALL_CONFIG = { debug: true }
}
// Load script
const script = document.createElement('script')
script.src = `https://adwall-backend-xxxxx.run.app/v1/loader/${siteId}.js`
script.async = true
document.body.appendChild(script)
// Cleanup
return () => {
script.remove()
}
}, [siteId, debug])
return null
}
Usage:
// app/layout.tsx
import { AdSentinelle } from '@/components/AdSentinelle'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<AdSentinelle siteId="YOUR_SITE_ID" />
</body>
</html>
)
}
Next.js (Pages Router)
// pages/_app.tsx
import Script from 'next/script'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
{/* Ad Sentinelle SDK */}
<Script
src="https://adwall-backend-xxxxx.run.app/v1/loader/YOUR_SITE_ID.js"
strategy="afterInteractive"
/>
</>
)
}
React (Create React App / Vite)
Method 1: In index.html
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My React App</title>
</head>
<body>
<div id="root"></div>
<!-- Ad Sentinelle SDK -->
<script src="https://adwall-backend-xxxxx.run.app/v1/loader/YOUR_SITE_ID.js" async></script>
</body>
</html>
Method 2: Custom Hook
// hooks/useAdSentinelle.ts
import { useEffect } from 'react'
interface UseAdSentinelleOptions {
siteId: string
debug?: boolean
onConverted?: () => void
onDetected?: () => void
}
export function useAdSentinelle({
siteId,
debug = false,
onConverted,
onDetected
}: UseAdSentinelleOptions) {
useEffect(() => {
// Configuration
if (debug) {
(window as any).ADWALL_CONFIG = { debug: true }
}
// Event listeners
const handleConverted = () => onConverted?.()
const handleDetected = () => onDetected?.()
window.addEventListener('adwall:converted', handleConverted)
window.addEventListener('adwall:detected', handleDetected)
// Load script
const script = document.createElement('script')
script.src = `https://adwall-backend-xxxxx.run.app/v1/loader/${siteId}.js`
script.async = true
document.body.appendChild(script)
// Cleanup
return () => {
script.remove()
window.removeEventListener('adwall:converted', handleConverted)
window.removeEventListener('adwall:detected', handleDetected)
}
}, [siteId, debug, onConverted, onDetected])
}
Usage:
// App.tsx
import { useAdSentinelle } from './hooks/useAdSentinelle'
function App() {
useAdSentinelle({
siteId: 'YOUR_SITE_ID',
debug: process.env.NODE_ENV === 'development',
onConverted: () => {
console.log('User converted!')
// Analytics, etc.
},
onDetected: () => {
console.log('Ad blocker detected')
}
})
return (
<div className="App">
{/* Your application */}
</div>
)
}
TypeScript Types
For better TypeScript integration, add these types:
// types/adwall.d.ts
interface AdSentinelleConfig {
debug?: boolean
delay?: number
cookieDomain?: string | null
}
interface AdSentinelleEventDetail {
sessionId: string
variant: string
timestamp: number
}
declare global {
interface Window {
ADWALL_CONFIG?: AdSentinelleConfig
AdSentinelle?: {
check: () => void
getSessionId: () => string
}
}
interface WindowEventMap {
'adwall:init': CustomEvent<AdSentinelleEventDetail>
'adwall:detected': CustomEvent<AdSentinelleEventDetail>
'adwall:displayed': CustomEvent<AdSentinelleEventDetail>
'adwall:converted': CustomEvent<AdSentinelleEventDetail>
'adwall:closed': CustomEvent<AdSentinelleEventDetail>
'adwall:error': CustomEvent<{ error: string }>
}
}
export {}
Environment Variables
Use environment variables to manage the Site ID:
# .env.local
NEXT_PUBLIC_ADWALL_SITE_ID=677c2846-fed7-4461-b69c-7717bc3be9b4
// components/AdSentinelle.tsx
const siteId = process.env.NEXT_PUBLIC_ADWALL_SITE_ID
<Script
src={`https://adwall-backend-xxxxx.run.app/v1/loader/${siteId}.js`}
strategy="afterInteractive"
/>
Disable in Development
// app/layout.tsx
import Script from 'next/script'
export default function RootLayout({ children }) {
const isProduction = process.env.NODE_ENV === 'production'
return (
<html lang="en">
<body>
{children}
{/* Ad Sentinelle only in production */}
{isProduction && (
<Script
src="https://adwall-backend-xxxxx.run.app/v1/loader/YOUR_SITE_ID.js"
strategy="afterInteractive"
/>
)}
</body>
</html>
)
}
Tip
In development, enable debug: true mode to see SDK logs in the console.