Next.js, Gatsby और Static Sites के लिए Cookie Consent: डेवलपर्स के लिए इंटीग्रेशन गाइड
स्टैटिक साइट्स में Consent की समस्या
Next.js, Gatsby और Nuxt.js जैसे आधुनिक JavaScript फ्रेमवर्क्स ने वेब पेजों के बनने और डिलीवर होने का तरीका बदल दिया है। पेज या तो बिल्ड टाइम पर या सर्वर पर पहले से प्री-रेंडर हो जाते हैं, और फिर क्लाइंट पर हाइड्रेट होते हैं। इससे कुकी कंसेंट के लिए एक अनोखी चुनौती पैदा होती है: कंसेंट बैनर को किसी भी ट्रैकिंग स्क्रिप्ट के चलने से पहले तैयार होना चाहिए, लेकिन पेज खुद पहले से रेंडर होकर edge पर कैश हो चुका हो सकता है।
पारंपरिक CMPs को सर्वर-रेंडर्ड PHP या साधारण HTML पेजों के लिए डिज़ाइन किया गया था, जहाँ डॉक्यूमेंट ऊपर से नीचे तक लाइनियर तरीके से लोड होता है। फ्रेमवर्क वाली दुनिया में, जहाँ code splitting, lazy loading और streaming server-side rendering होती है, ये धारणाएँ टूट जाती हैं। इन एनवायरनमेंट्स में सही तरीके से कंसेंट सेट करना रेंडरिंग पाइपलाइन को समझने पर निर्भर करत��� है।
टाइमिंग आपकी सोच से ज़्यादा अहम क्यों है
एक साधारण HTML पेज में, CMP स्क्रिप्ट को <head> में बाकी स्क्रिप्ट्स से पहले रखना आसान है। Next.js App Router या Gatsby में स्थिति ज़्यादा जटिल हो जाती है:
- प्री-रेंडर्ड HTML पहले आता है: ब्राउज़र को CDN या सर्वर से पूरा HTML मिलता है। अगर उस HTML में कोई inline स्क्रिप्ट या थर्ड-पार्टी टैग एम्बेडेड हैं, तो वे आपके कंसेंट लॉजिक के लोड होने से पहले ही चल सकते हैं।
- Hydration gap: React हाइड्रेशन HTML पेंट होने के बाद होता है। अगर आपका कंसेंट कंपोनेंट एक React कंपोनेंट है, तो हाइड्रेशन पूरा होने तक वह फंक्शनल ��्टेट में मौजूद ही नहीं होता। इस गैप के दौरान Google टैग्स या एनालिटिक्स स्क्रिप्ट्स बिना कंसेंट के फायर हो सकते हैं।
- Edge caching की जटिलताएँ: अगर आप ISR (Incremental Static Regeneration) या edge functions का इस्तेमाल करते हैं, तो HTML कैश हो जाता है। आप बिना क्लाइंट-साइड मैकेनिज़्म के cached HTML में कंसेंट-डिपेंडेंट लॉजिक डायनेमिकली इंजेक्ट नहीं कर सकते।
मूल सिद्धांत यह है: कंसेंट को कंपोनेंट लेवल पर नहीं, स्क्रिप्ट लेवल पर स्थापित करना चाहिए। एक React कंपोनेंट जो कंसेंट बैनर रेंडर करता है, अगर केवल हाइड्रेशन के बाद इंटरैक्टिव होता है, तो वह बहुत देर से आता है।
Next.js App Router इंटीग्रेशन
App Router के साथ Next.js 13+ ने स्क्रिप्ट्स को हैंडल करने का नया तरीका दिया है। कंसेंट इंटीग्रेशन के लिए अनुशंसित तरीका यह है:
स्टेप 1: Root Layout में CMP स्क्रिप्ट लोड करें
अपने root layout.tsx में Next.js के Script कंपोनेंट को beforeInteractive स्ट्रैटेजी के साथ इस्तेमाल करें। यह Next.js को बताता है कि हाइड्रेशन शुरू होने से पहले इस स्क्रिप्ट को शुरुआती HTML डॉक्यूमेंट में इंजेक्ट किया जाए:
beforeInteractive स्ट्रैटेजी बेहद अहम है। डिफ़ॉल्ट afterInteractive स्ट्रैटेजी स्क्रिप्ट्स को हाइड्रेशन के बाद लोड करती है, जो कंसेंट के लिए बहुत द���र हो जाती है। beforeInteractive के साथ CMP स्क्रिप्ट सर्वर-रेंडर्ड HTML में शामिल होती है और पेज लोड होते ही चल जाती है।
स्टेप 2: Google Tags से पहले डिफ़ॉल्ट कंसेंट सेट करें
अपने Google Tag Manager या gtag.js स्निपेट से पहले एक inline स्क्रिप्ट शामिल करें जो डिफ़ॉल्ट कंसेंट स्टेट्स सेट करे। इससे यह सुनिश्चित होता है कि भले ही GTM, CMP बैनर के दिखने से पहले लोड हो जाए, वह डिनाइड डिफ़ॉल्ट्स का सम्मान करेगा:
यह inline स्क्रिप्ट आपके root layout के <head> में, CMP और GTM स्क्रिप्ट्स से पहले रखी जानी चाहिए। Next.js में आप इस काम के लिए अपने layout के <head> एलिमेंट के अंदर एक साधारण <script> टैग का उपयोग कर सकते हैं।
स्टेप 3: Route Changes को हैंडल करें
Single-page application नेविगेशन में CMP स्क्रिप्ट एक बार लोड होती है, लेकिन route changes पर पूरा पेज रीलोड नहीं होता। आपका CMP क्लाइंट-साइड नेविगेशन के दौरान भी बना रहना चाहिए। FlexyConsent यह अपने आप हैंडल करता है — एक बार लोड होने के बाद यह बिना दोबारा इनिशियलाइज़ किए सभी route changes पर एक्टिव रहता है।
Next.js Pages Router इंटीग्रेशन
जो प्रोजेक्ट अभी भी Pages Router का इस्तेमाल कर रहे हैं, उनके लिए तरीका लगभग वही है, लेकिन root layout की जगह _document.tsx का उपयोग होता है। CMP स्क्रिप्ट को अपनी custom Document क्लास के <Head> कंपोनेंट में रखें। Pages Router में भी beforeInteractive स्ट्रैटेजी उसी तरह काम करती है।
मुख्य अंतर यह है कि _document.tsx केवल सर्वर पर रेंडर होता है, इसलिए यहाँ की कोई भी कंसेंट लॉजिक शुरुआती HTML payload में होना तय है।
Gatsby Static Site इंटीग्रेशन
Gatsby बिल्ड टाइम पर पूरी तरह स्टैटिक HTML जेनरेट करता है। रिक्वेस्ट टाइम पर कोई सर्वर-साइड रेंडरिंग नहीं होती, जिससे कुछ चीजें आसान हो जाती हैं, लेकिन कुछ और जटिल:
gatsby-ssr.tsxका उपयोग करें ताकि हर पेज के<head>में CMP स्क्रिप्ट इंजेक्ट की जा सके।onRenderBodyAPI आपको head में ऐसे स्क्रिप्ट्स जोड़ने देत��� है जो हर स्टैटिक HTML फाइल में मौजूद होंगे।- ऐसे Gatsby प्लगइन्स से बचें जो कंसेंट को lazy-load करते हैं: कुछ कम्युनिटी प्लगइन्स कंसेंट को React कंपोनेंट्स में wrap करते हैं जो केवल हाइड्रेशन के बाद mount होते हैं। इससे वही टाइमिंग गैप बनता है जिसकी चर्चा ऊपर हुई।
- कंसेंट डिफ़ॉल्ट्स को inline रखें:
gatsby-ssr.tsxमेंsetHeadComponentsका उपयोग करके एक inline स्क्रिप्ट जोड़ें जो डिफ़ॉल्ट कंसेंट स्टेट्स सेट करे। यह स्क्रिप्ट स्टैटिक HTML में होगी और तुरंत execute होगी।
Gatsby का build-time एप्रोच मतलब यह है कि आपके CDN पर हर HTML फाइल में कंसेंट स्क्रिप्ट शामिल होगी। यह वास्तव में आदर्श है — यहाँ कोई सर्वर लॉजिक नहीं है जो फेल हो सके या गलत तरीके से कैश हो सके।
Nuxt.js से जुड़ी बातें
Nuxt.js (Vue-आधारित) के अपने पैटर्न हैं। Nuxt 3 में, CMP स्क्रिप्ट को ग्लोबली जोड़ने के लिए useHead composable या nuxt.config.ts की app head कॉन्फ़िगरेशन का उपयोग करें। Nuxt body: false ऑप्शन सपोर्ट करता है (जो स्क्रिप्ट्स को head में रखता है) और non-blocking लोडिंग के लिए async एट्रिब्यूट भी।
Nuxt के server-side rendering मोड के लिए भी वही सिद्धांत लागू होता है: CMP स्क्रिप्ट शुरुआती HTML response में होनी चाहिए, न कि Vue कंपोनेंट द्वारा mount होने के बाद डायनेमिकली इंजेक्ट की ज��ए।
Layout Shift से बचना
कंसेंट बैनर्स Cumulative Layout Shift (CLS) के लिए बदनाम हैं, जो एक Core Web Vital है और SEO रैंकिंग को प्रभावित करता है। जब बैनर पेज रेंडर होने के बाद अचानक दिखता है, तो वह कंटेंट को नीचे धकेल देता है या अनपेक्षित रूप से overlay कर देता है।
कंसेंट बैनर्स से CLS कम करने की रणनीतियाँ:
- बॉटम-पोज़िशन वाला बैनर इस्तेमाल करें: viewport के नीचे वाले बैनर पेज कंटेंट को शिफ्ट नहीं करते। CLS के लिहाज़ से यह सबसे बेहतर तरीका है।
- स्पेस रिज़र्व करें: अगर आपको टॉप बैनर ही इस्तेमाल करना है, तो अपने CSS में उसके लिए वर्टिकल स्पेस पहले से र���ज़र्व कर दें, ताकि पेज लेआउट बैनर को रेंडर होने से पहले ही ध्यान में रखे।
- लोड पर modal overlays से बचें: फुल-स्क्रीन कंसेंट वॉल्स जो पेज रेंडर होने के बाद दिखते हैं, लेआउट को अस्थिर महसूस कराते हैं। अगर आपको वॉल की ज़रूरत है, तो उसे शुरुआती पेज स्टेट का हिस्सा बनाकर रेंडर करें।
- CMP को head में सिंक्रोनसली लोड करें: जब CMP को head में render-blocking स्क्रिप्ट के रूप में लोड किया जाता है, तो बैनर शुरुआती पेंट का हिस्सा बन सकता है, बाद में पॉप-इन होने की बजाय।
FlexyConsent का Framework-Agnostic एप्रोच
FlexyConsent को किसी भी फ्रेमवर्क — या बिना किसी फ्रेमवर्क ��� के साथ काम करने के लिए डिज़ाइन किया गया है, क्योंकि यह कंपोनेंट लेवल की बजाय स्क्रिप्ट लेवल पर ऑपरेट करता है। यह क्यों मायने रखता है:
- एक ही async स्क्रिप्ट टैग:
<head>में केवल एक<script>टैग की ज़रूरत होती है। कोई npm पैकेज इंस्टॉल नहीं करना, कोई फ्रेमवर्क-स्पेसिफिक wrapper नहीं, कोई build कॉन्फ़िगरेशन नहीं। - कंसेंट डिफ़ॉल्ट्स तुरंत फायर होते हैं: स्क्रिप्ट अपनी पहली ही कार्रवाई के रूप में Consent Mode V2 डिफ़ॉल्ट्स सेट करती है, किसी callback या DOM manipulation से पहले। इसका मतलब है कि Google टैग्स पहले ही मिलीसेकंड से कंसेंट का सम्मान क��ते हैं।
- DOM पर निर्भरता नहीं: कंसेंट लॉजिक React, Vue या Svelte के हाइड्रेट होने का इंतज़ार नहीं करता। यह फ्रेमवर्क लाइफसाइकल से स्वतंत्र रूप से काम करता है।
- SSG, SSR, ISR और CSR के साथ काम करता है: क्योंकि यह एक साधारण स्क्रिप्ट है, यह उसी तरह काम करती है, चाहे पेज स्टैटिकली जेनरेट हुआ हो, सर्वर-रेंडर्ड हो, incrementally regenerate हुआ हो या क्लाइंट-साइड रेंडर्ड हो।
डेवलपर टिप: सही CMP इंटीग्रेशन की सबसे आसान टेस्ट यह है कि ब्राउज़र का Network टैब खोलें, Google डोमेन्स से फ़िल्टर करें और पेज को रीलोड करें। कंसेंट डिफ़ॉल्ट कमांड के कंसोल मे�� दिखने से पहले कोई भी Google रिक्वेस्ट फायर नहीं होनी चाहिए। अगर होती है, तो आपका CMP बहुत देर से लोड हो रहा है।
FlexyConsent का फ्री प्लान अनलिमिटेड pageviews सपोर्ट करता है और Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix और plain HTML के साथ काम करता है। इन सबमें इंटीग्रेशन एक जैसा है: एक स्क्रिप्ट टैग, सही जगह पर रखा हुआ।