Next.js + React integration layer for the Consentry SDK. Manages cookie preferences, script injection, and analytics sync.
npm install @consentry/next> Next.js integration for Consentry consent management. React hooks, providers, and automatic script injection — works seamlessly with @consentry/ui for a complete solution.
---
- ⚛️ React Context Provider — manages consent state across your app
- 🪝 Custom hooks — useConsentManager() for easy state access
- 📜 Automatic script injection — loads scripts based on user consent
- 🔄 Google Analytics integration — automatic consent mode v2 updates
- 🎨 UI component ready — pairs perfectly with @consentry/ui
- 🚀 Next.js optimized — works with App Router and Pages Router
---
``bash`
npm install @consentry/next @consentry/ui @consentry/core
`bash`
npm install @consentry/next @consentry/core
---
👑 This is the recommended approach — using @consentry/next with @consentry/ui gives you a complete, plug-and-play consent management solution.
Create providers/consent-provider.tsx:
`tsx
"use client";
import { ConsentConfig, ConsentManagerProvider } from "@consentry/next";
import ConsentManager from "@consentry/ui";
const ConsentProvider = ({ children }: { children: React.ReactNode }) => {
const consentConfig: ConsentConfig = {
debug: process.env.NODE_ENV === "development",
defaults: {
functional: true,
performance: false,
advertising: false,
social: false,
},
scripts: [
{
id: "gtag-js",
category: "performance",
consentRequired: true,
strategy: "afterInteractive",
src: "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX",
vendor: "Google Analytics",
},
{
id: "gtag-init",
category: "performance",
consentRequired: true,
strategy: "afterInteractive",
content:
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
gtag('consent', 'default', {
analytics_storage: 'denied',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied'
});
,
vendor: "Google Analytics",
},
],
};
return (
{children}
);
};
export default ConsentProvider;
`
App Router (app/layout.tsx):
`tsx
import ConsentProvider from "@/providers/consent-provider";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
Pages Router (
pages/_app.tsx):`tsx
import ConsentProvider from "@/providers/consent-provider";
import type { AppProps } from "next/app";export default function App({ Component, pageProps }: AppProps) {
return (
);
}
`$3
`tsx
"use client";
import { useConsentManager } from "@consentry/next";export default function PrivacySettings() {
const { preferences, updatePreferences, hasConsentedOnce } = useConsentManager();
if (!hasConsentedOnce) {
return
Please accept or decline cookies first.
;
} return (
Your Privacy Settings
);
}
`That's it! You now have a complete consent management system with banner, modal, and programmatic control.
---
🎛️ Core Components
$3
The main provider that manages all consent state and script injection.
`tsx
interface ConsentManagerProviderProps {
config: ConsentConfig; // Your consent configuration
children: React.ReactNode; // Your app content
storageKey?: string; // Custom localStorage key (default: 'consentry-preferences')
debug?: boolean; // Enable debug logging
}
`$3
Access consent state and controls from any component.
`tsx
const {
preferences, // Current user preferences
updatePreferences, // Update all preferences
setCategoryConsent, // Update single category
hasConsentedTo, // Check specific category
hasConsentedOnce, // Has user made any choice?
acceptAll, // Accept all categories
rejectAll, // Reject all (except functional)
resetConsent, // Clear all consent data
} = useConsentManager();
`---
📋 Complete API Reference
$3
`tsx
interface ConsentConfig {
debug?: boolean; // Enable debug logging
defaults: CookiePreferences; // Default consent state
scripts: ConsentScript[]; // Scripts to manage
storageKey?: string; // Custom storage key
googleAnalyticsId?: string; // GA4 tracking ID for auto-setup
}
`$3
`tsx
interface CookiePreferences {
functional: boolean; // Always true (required for site function)
performance: boolean; // Analytics, monitoring, A/B testing
advertising: boolean; // Marketing pixels, retargeting
social: boolean; // Social media embeds, sharing
}
`$3
`tsx
interface ConsentScript {
id: string; // Unique identifier
category: ConsentCategory; // Which consent category
consentRequired?: boolean; // Require explicit consent
strategy?: "afterInteractive" | "lazyOnload" | "beforeInteractive";
src?: string; // External script URL
content?: string; // Inline script content
noscript?: string; // Fallback for no-JS
vendor?: string; // Third-party service name
default?: boolean; // Load by default
}
`$3
`tsx
interface ConsentManagerHook {
preferences: CookiePreferences;
updatePreferences: (preferences: CookiePreferences) => void;
setCategoryConsent: (category: ConsentCategory, granted: boolean) => void;
hasConsentedTo: (category: ConsentCategory) => boolean;
hasConsentedOnce: () => boolean;
acceptAll: () => void;
rejectAll: () => void;
resetConsent: () => void;
}
`---
🔧 Configuration Examples
$3
`tsx
const gaConfig: ConsentScript[] = [
{
id: "gtag-js",
category: "performance",
consentRequired: true,
strategy: "afterInteractive",
src: "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX",
vendor: "Google Analytics",
},
{
id: "gtag-init",
category: "performance",
consentRequired: true,
strategy: "afterInteractive",
content: ,
vendor: "Google Analytics",
},
];
`$3
`tsx
const facebookPixel: ConsentScript = {
id: "facebook-pixel",
category: "advertising",
consentRequired: true,
strategy: "afterInteractive",
content: ,
noscript: ,
vendor: "Meta",
};
`$3
`tsx
const consentConfig: ConsentConfig = {
debug: process.env.NODE_ENV === "development",
defaults: {
functional: true,
performance: false,
advertising: false,
social: false,
},
scripts: [
// Google Analytics
...gaConfig, // Hotjar
{
id: "hotjar",
category: "performance",
consentRequired: true,
strategy: "afterInteractive",
content:
,
vendor: "Hotjar",
}, // Facebook Pixel
facebookPixel,
// Twitter Pixel
{
id: "twitter-pixel",
category: "advertising",
consentRequired: true,
strategy: "afterInteractive",
content:
,
vendor: "Twitter",
},
],
};
`---
💡 Usage Patterns
$3
`tsx
"use client";
import { useConsentManager } from "@consentry/next";
import { openConsentSettings } from "@consentry/ui";export default function Footer() {
const { hasConsentedOnce, acceptAll, rejectAll } = useConsentManager();
return (
);
}
`$3
`tsx
"use client";
import { useConsentManager } from "@consentry/next";export default function AnalyticsDashboard() {
const { hasConsentedTo } = useConsentManager();
if (!hasConsentedTo("performance")) {
return (
Analytics data requires performance cookies.
);
} return
{/ Your analytics dashboard /};
}
`$3
`tsx
"use client";
import { useConsentManager } from "@consentry/next";export default function YouTubeEmbed({ videoId }: { videoId: string }) {
const { hasConsentedTo, setCategoryConsent } = useConsentManager();
if (!hasConsentedTo("social")) {
return (
This content requires social media cookies.
);
} return (
src={
https://www.youtube.com/embed/${videoId}}
width="560"
height="315"
frameBorder="0"
allowFullScreen
/>
);
}
`$3
`tsx
import { useConsentManager } from "@consentry/next";
import { useCallback } from "react";export function useAnalytics() {
const { hasConsentedTo, setCategoryConsent } = useConsentManager();
const trackEvent = useCallback(
(event: string, data?: any) => {
if (hasConsentedTo("performance") && typeof gtag !== "undefined") {
gtag("event", event, data);
}
},
[hasConsentedTo]
);
const enableAnalytics = useCallback(() => {
setCategoryConsent("performance", true);
}, [setCategoryConsent]);
return {
trackEvent,
enableAnalytics,
analyticsEnabled: hasConsentedTo("performance"),
};
}
// Usage
function MyComponent() {
const { trackEvent, analyticsEnabled } = useAnalytics();
const handleClick = () => {
trackEvent("button_click", { button_id: "header_cta" });
};
return ;
}
`---
🛠️ Advanced Configuration
$3
`tsx
const getConsentConfig = (): ConsentConfig => {
const isProd = process.env.NODE_ENV === "production"; return {
debug: !isProd,
defaults: {
functional: true,
performance: isProd, // Auto-enable in production
advertising: false,
social: false,
},
scripts: isProd ? productionScripts : developmentScripts,
};
};
`$3
`tsx
{children}
`$3
`tsx
"use client";
import dynamic from "next/dynamic";// Avoid hydration issues
const ConsentManager = dynamic(() => import("@consentry/ui"), {
ssr: false,
});
const ConsentProvider = ({ children }: { children: React.ReactNode }) => {
return (
{children}
);
};
`---
🧪 Testing
$3
`tsx
// __mocks__/@consentry/next.ts
export const useConsentManager = () => ({
preferences: {
functional: true,
performance: true,
advertising: false,
social: false,
},
updatePreferences: jest.fn(),
setCategoryConsent: jest.fn(),
hasConsentedTo: jest.fn(() => true),
hasConsentedOnce: jest.fn(() => true),
acceptAll: jest.fn(),
rejectAll: jest.fn(),
resetConsent: jest.fn(),
});
`$3
`tsx
import { render, screen } from "@testing-library/react";
import { useConsentManager } from "@consentry/next";
import MyComponent from "./MyComponent";jest.mock("@consentry/next");
test("shows analytics when performance cookies enabled", () => {
(useConsentManager as jest.Mock).mockReturnValue({
hasConsentedTo: (category: string) => category === "performance",
});
render( );
expect(screen.getByText("Analytics Dashboard")).toBeInTheDocument();
});
`---
🔒 Privacy & Compliance
$3
- Consent before tracking — Scripts only load after explicit consent
- Granular control — Users choose specific categories
- Easy withdrawal — One-click preference changes
- Data portability — Export/import consent settings
$3
The provider automatically handles Google's consent mode v2:
`tsx
// Automatically called when preferences change
gtag("consent", "update", {
analytics_storage: preferences.performance ? "granted" : "denied",
ad_storage: preferences.advertising ? "granted" : "denied",
ad_user_data: preferences.advertising ? "granted" : "denied",
ad_personalization: preferences.advertising ? "granted" : "denied",
});
`---
🚨 Common Issues & Solutions
$3
`tsx
// ❌ Wrong - causes hydration issues
export default function Layout({ children }) {
return (
{children}
);
}// ✅ Correct - use dynamic import
const ConsentManager = dynamic(() => import("@consentry/ui"), { ssr: false });
`$3
`tsx
// ❌ Wrong - bypasses consent management
;// ✅ Correct - managed by consent system
scripts: [
{
id: "analytics",
category: "performance",
src: "https://analytics.example.com/script.js",
},
];
`$3
`tsx
// ❌ Wrong - hook used outside provider
function App() {
const { preferences } = useConsentManager(); // Error!
return ...;
}// ✅ Correct - hook used inside provider
function App() {
return (
);
}
function MyComponent() {
const { preferences } = useConsentManager(); // Works!
return
...;
}
`---
🔗 Related Packages
@consentry/core — Framework-agnostic consent logic
- @consentry/ui — React components for banners and modals$3
@consentry/ui` documentation which includes:- 🎨 Customizable cookie banners and modals
- 🌈 Color themes and styling options
- 🌍 Multi-language support
- 📱 Mobile-optimized responsive design
- ♿ Full accessibility support
---
MIT — Copyright © 2025 Mustafa ONAL