NordBastion का polar-bear mascot एक तराशे गए Nordic पत्थर के lectern पर खड़ा है, उसके ऊपर एक बड़ा तैरता हुआ cyan holographic dashboard है जिसमें bar charts, एक चढ़ती हुई line graph और एक amber accent वाली donut ring दिख रही है, और cyan बिंदुओं की एक अटूट धारा एक aurora से जगमगाती arched खिड़की से निकलकर dashboard से गुज़रते हुए एक runed vault दरवाज़े में जा रही है, पीछे एक server rack के साथ
हाउ-टू · Analytics·18 मिनट पठन · 40 मिनट व्यावहारिक अभ्यास

आपने अपने पाठकों पर नज़र रखने के लिए एक script लगाई थी।
यह पलटकर आप पर नज़र रखता है, और कहीं और report करता है।

Analytics सबसे आख़िरी third-party tag है जिसे ज़्यादातर लोग बनाए रखते हैं, और यही वह है जो सब कुछ देखता है: हर page, हर reader, हर घंटा — एक ऐसे system पर जो न आपका है, न जिसे आप audit कर सकते हैं। इसे अपने खुद के एक counter से बदलने के छह चरण — Umami, Plausible Community Edition, Matomo या फिर सिर्फ़ server log — जो किसी पहचान-दस्तावेज़ के बिना किराए पर लिए गए एक Nordic box पर चलता है। डिफ़ॉल्ट रूप से cookie-रहित, बहस के लिए कोई banner नहीं, और आपके पाठकों का किसी तीसरे देश में कोई transfer नहीं। $3.90 प्रति माह से शुरू। Debian 12 पर परखा गया।

छह चरण
  1. 01

    चुनें

    चार tools, एक ईमानदार table

  2. 02

    Provision

    एक subdomain, तीन ports

  3. 03

    तैनात करें

    Compose, Caddy, पहला login

  4. 04

    मापें

    एक tag, और first-party रास्ता

  5. 05

    पालन करें

    एक नहीं, दो कानून

  6. 06

    Keep

    Retention, backups, वह भुला दिया गया log

शुरू करने से पहले · tag क्या है

यह कोई counter नहीं है। यह एक reporting line है।

visitors को गिनना सचमुच उपयोगी है, और ऐसा चाहने में कुछ भी संदेहास्पद नहीं है। आपको यह जानना होता है कि rewrite से फ़ायदा हुआ या नहीं, कौन-सा article लोग वाकई पूरा पढ़ते हैं, कौन-सा referrer bounce के बजाय असली readers भेजता है, और क्या पिछली रात के deploy ने चुपचाप किसी एक browser पर checkout तोड़ दिया। इन सारे सवालों का जवाब page views की एक table दे देती है, और इनमें से हर एक measure करने की एक वाजिब वजह है।

जिस चीज़ को सीधे देखना ज़रूरी है वह वह व्यवस्था है जिसे लगभग सबने ये जवाब पाने के लिए स्वीकार कर लिया। standard analytics tag एक ऐसा code है, जिसे एक विज्ञापन कंपनी ने लिखा है, जिसे आप अपनी site के हर page पर लगाते हैं और अपने पाठक के browser में चलाने का निर्देश देते हैं। यह page का address, referrer, screen, भाषा, device पढ़ता है; यह device पर एक identifier सेट या पढ़ता है; यह यह सब एक ऐसे system को भेजता है जिसे आप जाँच नहीं सकते, एक ऐसे देश में जिसके नियम आपने नहीं चुने; और यह बना हुआ file एक ऐसी कंपनी को थमा देता है जिसकी आमदनी इस बात से आती है कि वह जानती है लोग क्या करते हैं। site के मालिक को एक dashboard मिलता है। dashboard इस पूरे सौदे का छोटा आधा हिस्सा है।

यह बिल चार किस्तों में आता है, और इनमें से सिर्फ़ एक ही साफ़ नज़र आती है। पहली है सहमति banner, जो लगभग पूरी तरह इस एक tag की वजह से मौजूद है, जो शुरुआत में ही आपके visitors का एक नापने-लायक हिस्सा छीन लेता है, और जिसे संभालने के लिए आप फिर एक दूसरे vendor को पैसे देते हैं। फिर है transfer वाला सवाल, क्योंकि आपके पाठकों का data किसी तीसरे देश के लिए निकल जाता है, और आख़िरकार किसी को यह लिखना पड़ता है कि यह क़ानूनी क्यों है। फिर है data ख़ुद, जो आपके पाठक हैं, एक ऐसे database में जिसे आप उन reports के अलावा query नहीं कर सकते जो आपको दी जाती हैं। और फिर है dependency: product किसी और के schedule पर retire, rename या restructure हो जाता है, और पिछली बार जब ऐसा हुआ था, पुराने measurements भी उसके साथ चले गए थे।

Self-hosting इन चारों को एक साथ हटा देता है, और यह कोई बड़ा काम नहीं है। software परिपक्व, मुफ़्त और उबाऊ है; box की क़ीमत महीने के कुछ ही dollars है; काम बस एक शाम का है। बदले में आपको मिलती है एक ऐसी table जो आपकी अपनी है, ऐसे hardware पर जो आपके चुने हुए अधिकार-क्षेत्र में है, जिसमें कोई तीसरा पक्ष बताने को नहीं है और — ज़्यादातर configurations में — बहस के लिए कोई banner नहीं। यह जानने के चार तरीके कि आपकी site कितने लोग पढ़ते हैं, और हर एक की क़ीमत क्या है:

विशेषता वह बड़ा मुफ़्त analytics tag एक निजता-केंद्रित analytics SaaS वही software, आपका VPS
पाठकों वाली table किसके पास हैएक विज्ञापन कंपनीएक vendor, contract के तहतआप, disk पर
सहमति banner ज़रूरीहाँ, व्यवहार में हमेशाआम तौर पर नहींआम तौर पर नहीं — step 05 देखें
Data EEA से बाहर जाता हैहाँ, डिज़ाइन से हीvendor पर निर्भर करता हैसिर्फ़ तब जब आप इसके बाहर कोई box चुनें
बताने योग्य Third partiesकम से कम एक, साथ में इसके subprocessorsएक processorकोई नहीं
filter lists द्वारा blockबहुत ज़्यादाअक्सर, hostname के हिसाब सेशायद ही कभी, एक बार यह first-party बन जाए तो
आपके लिए उपलब्ध raw dataनहीं — सिर्फ़ reportsएक API के ज़रिए, जब तक आप पैसे देते रहेंयह आपका database है
100k views पर मासिक लागतपैसों में कुछ भी नहींदहाई अंकों के dollars, traffic के साथ बढ़ते हुए$3.90–$7.90, फ़्लैट
इसे चुनें जबआपको ad-platform integration चाहिए और बाक़ी सब मंज़ूर हैआपको बिना कुछ चलाए वह नैतिकता चाहिएपाठक आपके हैं, और table भी आपकी है

तीसरा column एक असली जवाब है, कोई straw man नहीं: एक hosted निजता-केंद्रित vendor उन्हीं में से ज़्यादातर समस्याओं को उन लोगों के लिए हटा देता है जिन्हें server नहीं चलाना चाहिए, और किसी एक को पैसे देना ad tag बनाए रखने से बेहतर नतीजा है। यह गाइड उस स्थिति के लिए है जिसमें आप पहले से कोई box किराए पर लेते हैं, या लेने वाले थे।

Step 01 · चुनें

चार tools। database ही bill तय करता है।

ये चार, एक ही चीज़ के चार अलग-अलग स्वाद नहीं हैं। ये इस बात में अलग हैं कि data को किसमें store करते हैं, और यही एक चुनाव memory footprint, disk का बढ़ना, upgrade का जोखिम और reports की गहराई तय कर देता है। पहले storage वाला column पढ़ें और फिर feature वाला column; असल फ़ैसला इसी क्रम में होता है।

टूल Stack और storage उचित tier इसे किसलिए चुनें
UmamiNode application + PostgreSQL या MySQL। दो containers।Sentinel · $3.90डिफ़ॉल्ट जवाब। हल्का, पढ़ने-योग्य, cookie-रहित, multi-site, MIT-licensed।
Plausible Community EditionElixir application + PostgreSQL + ClickHouse। चार containers।Garrison · $7.90Goals, funnels और public dashboards; उच्च volume पर तेज़ queries।
MatomoPHP application + MariaDB, साथ में एक scheduled archiving job।Garrison · $7.90incumbent के साथ feature parity — segments, cohorts, e-commerce, log import।
GoAccessएक binary जो web server access log पढ़ता है। कोई database नहीं।जो भी आप पहले से चला रहे हैंबिल्कुल कोई JavaScript नहीं — static sites, documentation, APIs।

Umami वह विकल्प है जिसकी ओर आपको बढ़ना चाहिए, जब तक कि कोई ठोस वजह न हो कि आप ऐसा न करें। यह एक ही relational database पर चलने वाला Node application है, यह एक gigabyte memory में संतुष्ट रहता है, इसका schema बस कुछ tables का है जिन्हें आप खुद query कर सकते हैं, और इसकी reports वही दिखाती हैं जो ज़्यादातर लोग dashboard खोलकर देखना चाहते हैं: pages, referrers, countries, devices, और चाहें तो custom events भी। यह डिफ़ॉल्ट रूप से cookie-रहित है और इसके लिए आपको कुछ भी configure नहीं करना पड़ता।

Plausible Community Edition hosted product का self-hostable संस्करण है, और इसका अतिरिक्त हिस्सा है ClickHouse — एक column store जो करोड़ों rows पर aggregate queries को भी तुरंत जैसा बना देता है, और जो आपके दिए जितनी भी memory इस्तेमाल कर लेता है। यह कुछ मिलियन मासिक views से ऊपर एक उचित trade-off है, और उससे नीचे थोड़ा अटपटा। deploy करने से पहले project की licence शर्तें पढ़ लें: community edition अपनी खुद की analytics चलाने के लिए है, इसे किसी service के रूप में resell करने के लिए नहीं।

Matomo चार में से एकमात्र ऐसा tool है जो incumbent को feature-दर-feature सचमुच replace करता है, और इस बात की ईमानदारी दोनों दिशाओं में असर डालती है: आपको segments, funnels, cohorts, e-commerce attribution, plugins के ज़रिए heatmaps, और अपने server logs import करने की क्षमता मिलती है, और साथ ही एक बड़ा PHP application भी मिलता है जिसकी raw tables तेज़ी से बढ़ती हैं और जिसकी reports एक archiving job द्वारा पहले से compute की जाती हैं, जिसे आपको खुद schedule करना होता है। फिर भी दो बातें इसे देखने लायक बनाती हैं: इसे कोई cookie सेट न करने के लिए configure किया जा सकता है, और इसके audience-measurement configurations regulators की उन प्रकाशित सूचियों में शामिल रहे हैं जो सहमति से exempt tools बताती हैं — किसी blog post के बजाय current list ज़रूर जाँच लें, लेकिन कागज़ पर यह एक वास्तविक फ़ायदा है।

GoAccess वह विकल्प है जिसे कोई सुझाता नहीं, मगर कई लोगों को इसे अपनाना चाहिए। यह आपके web server द्वारा पहले से लिखे जा रहे access log को पढ़ता है और उसे एक terminal report या एक self-contained HTML page के रूप में प्रस्तुत करता है। browser में कुछ नहीं चलता, device पर कुछ भी संग्रहीत नहीं होता, और सहमति संबंधी कोई सवाल नहीं उठता क्योंकि request के अलावा कोई collection ही नहीं है। आप जो खो देते हैं वह है page के भीतर होने वाली हर गतिविधि, और requests के बजाय लोगों को गिनने की कोई भी उम्मीद। किसी documentation site या static blog के लिए यह अक्सर एक उचित trade-off है — और यह किसी अन्य tool की जगह लेने के बजाय उसके साथ मिलकर बेहतर काम करता है।

एक पंक्ति में फ़ैसला

अगर आप यह नहीं बता सकते कि आपको Plausible या Matomo से कौन-सी ख़ास feature चाहिए, तो आपको Umami चाहिए। इसे बीस मिनट में deploy करें, एक महीने तक चलाएँ, और जिस सवाल का जवाब आप खुद नहीं दे पा रहे, उसे ही यह तय करने दें कि आगे बढ़ना है या नहीं। बाद में migrate करने पर सिर्फ़ history का नुक़सान होता है, और कुछ नहीं, और जो history आप खोएँगे वह बस एक महीने की है।

Step 02 · जुटाएँ

एक box, एक नाम। पहले नाम तय करें।

VPS order करें और bastion का चुनाव इस आधार पर करें कि आपके पाठक कहाँ हैं और आप data को कहाँ रखना चाहते हैं — Stockholm, Helsinki, Oslo या Reykjavík, सभी EEA के भीतर हैं, और यही असली बात है। फिर बाकी कुछ भी box को छूने से पहले पहले घंटे वाला hardening pass चलाएँ: key-only SSH, एक बदला हुआ port, एक default-deny firewall, unattended upgrades। यह इस सीरीज़ के हर गाइड में वही चालीस मिनट हैं, और यह उस machine पर वैकल्पिक नहीं है जो किसी के एक साल के पाठकों को थामने वाली हो।

फिर hostname तय कर लें, क्योंकि यह उस tracking snippet में पक्का बैठा होता है जो आपके measure की जाने वाली हर site के हर page पर है, और इसे बाद में बदलने का मतलब है उन सभी को edit करना जबकि पुराना नाम अब भी hits पाता रहता है। दो तरीक़े काम करते हैं। जिस site को आप measure कर रहे हैं उसका अपना एक subdomain — analytics box पर मौजूद reverse proxy इसके लिए जवाब देता है, और यह सबसे सरल तरीका है जो काम करता है। या फिर अपने ही किसी domain पर एक neutral नाम, अगर एक instance कई असंबंधित sites को सेवा देगा और आप चाहते हैं कि हर site का source बाकियों का विज्ञापन न करे। आगे बढ़ने से पहले record बनाएँ और उसे resolve होने दें: proxy पहली बार शुरू होने पर किसी certificate authority से certificate माँगता है, और वह authority बाहर से नाम की जाँच करती है।

dig +short stats.example.com          # must return the VPS address before you deploy
ufw default deny incoming
ufw allow 47222/tcp                  # administrative SSH, moved off 22
ufw allow 80/tcp                     # ACME challenge and the redirect to 443
ufw allow 443/tcp                    # the dashboard and the collection endpoint
ufw enable && ufw status numbered

तीन ports, और कुछ नहीं। database publish नहीं होना चाहिए: यह internal Docker network पर रहता है, जिस तक application container पहुँच सकता है और internet पर कोई और नहीं। यही वह सबसे आम तरीक़ा है जिससे कोई self-hosted analytics box किसी scan result में आ जाता है — एक PostgreSQL या MySQL port public address से बंधा हुआ, क्योंकि किसी tutorial की Compose file में एक ports mapping थी जो local development के लिए रखी गई थी।

sizing को लेकर, ज़्यादा ख़रीदने की चाहत पर काबू रखें। एक Sentinel — 2 vCPU, 4 GB, 120 GB NVMe, $3.90 प्रति माह — Umami और Postgres को गुंजाइश के साथ चला देता है, और उस site के लिए बरसों के events थाम सकता है जिसके मासिक views छह अंकों में हों। अगर आपने Plausible चुना है तो Garrison — 4 vCPU, 8 GB, 240 GB — पर चले जाएँ, क्योंकि वहाँ ClickHouse ज़्यादा सहज रहता है, या Matomo के लिए, क्योंकि archiving job को ज़्यादा cores चाहिए। हर tier पर bandwidth असीमित है और analytics traffic उसके सामने एक rounding error जैसा है: हर hit बस कुछ सौ bytes का होता है।

Step 03 · तैनात करें

दो containers और एक proxy। फिर दरवाज़ा बंद करें।

नीचे दिया गया reference deployment Umami है, क्योंकि यही वह है जो ज़्यादातर readers को चलाना चाहिए, और क्योंकि इसका आकार सामान्यीकृत होता है: एक application container, एक database container जिस तक यह पहुँच सकता है और कोई और नहीं, और certificate थामे एक reverse proxy। Plausible और Matomo containers की संख्या और variables के नामों में अलग हैं, structure में नहीं — उनकी official Compose files लें और वही तीन नियम लागू करें।

तीन नियम, इस क्रम में कि अगर इन्हें नज़रअंदाज़ किया जाए तो ये आपको कितना महँगा पड़ेंगे। हर image को एक तय tag पर pin करें, किसी floating tag पर कभी नहीं: एक analytics stack जो किसी असंबंधित reboot के दौरान चुपचाप एक नया major version खींच लाए, वह एक ऐसा schema migration है जिसे आपने schedule नहीं किया था। application secret को एक असली random source से generate करें और उसे सुरक्षित रखें — यह session सामग्री को encrypt करता है, और इसे बाद में बदलने पर सबसे अच्छी स्थिति में भी सब लोग log out हो जाते हैं। कोई database port publish न करें: दोनों containers एक network साझा करते हैं और उन्हें बस यही access control चाहिए।

mkdir -p /srv/analytics && cd /srv/analytics
openssl rand -base64 32 > .app_secret      # keep this file; back it up with the database
openssl rand -base64 24 > .db_password
chmod 600 .app_secret .db_password

Compose file। दो services, एक private network, database के लिए एक named volume, और एक भी published port नहीं — proxy ही अकेली ऐसी चीज़ है जो बाहरी दुनिया से बात करती है:

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-v2.x.y   # an exact tag, never :latest
    environment:
      DATABASE_URL: postgresql://umami:CHANGE_ME@db:5432/umami
      APP_SECRET:   CHANGE_ME                                # the openssl output above
    depends_on: [db]
    restart: unless-stopped
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB:       umami
      POSTGRES_USER:     umami
      POSTGRES_PASSWORD: CHANGE_ME
    volumes:
      - umami-db:/var/lib/postgresql/data
    restart: unless-stopped
volumes:
  umami-db:

यहाँ एक सही TLS setup तक पहुँचने का सबसे छोटा रास्ता Caddy है: configuration की सिर्फ़ दो पंक्तियाँ, एक certificate जो बिना किसी cron job के हासिल और renew होता रहता है, और modern defaults जिन पर आपको खुद research नहीं करनी पड़ती। अगर आप box पर पहले से ही nginx चला रहे हैं, तो nginx को ही बने रहने दें — ज़रूरत सामने किसी proxy की है, इसी ख़ास proxy की नहीं। दोनों ही स्थितियों में analytics application को कभी भी सीधे 443 पर सुनने वाली चीज़ नहीं होना चाहिए।

# Caddyfile — Caddy runs as a third service in the same Compose project, so
# "umami" resolves on the internal network. It is the only service that
# publishes ports (80 and 443).
stats.example.com {
    encode zstd gzip
    reverse_proxy umami:3000
}

इसे खड़ा करें, फिर वह एक काम करें जो सचमुच समय की दृष्टि से नाज़ुक है। docker compose up -d चलाएँ, migrations का इंतज़ार करें, और dashboard खोलें। इनमें से हर tool या तो एक दर्ज किया हुआ default administrator account लेकर आता है या एक खुली first-registration screen, और hostname certificate जारी होते ही सार्वजनिक जानकारी बन जाता है, क्योंकि certificate transparency logs सार्वजनिक होते हैं और लगातार scrape किए जाते हैं। पहली सफल load के कुछ ही मिनटों के भीतर default password बदल दें और registration बंद कर दें, कल नहीं।

docker compose up -d
docker compose logs -f umami          # wait for the schema migration to finish
docker compose ps                     # both services healthy, no published ports listed
ss -tlnp | grep -E ':(5432|3306)'     # must print nothing at all
वे पाँच मिनट जो तय करते हैं कि instance का मालिक कौन है

Umami एक दर्ज किया हुआ administrator account लेकर आता है जिसका password धरती की हर installation पर एक जैसा है। अगर environment में registration बंद न किया जाए, तो Plausible का पहला visitor ही owner बन जाता है। Matomo पहले visitor को एक installer से गुज़ारता है जो superuser बनाता है। तीनों ही मामलों में "certificate मौजूद है" और "आप log in हो गए" के बीच का समय एक ऐसी खिड़की है जिसमें कोई और आपकी जगह log in कर सकता है — और उन्हें hostname अंदाज़ा लगाने की भी ज़रूरत नहीं, क्योंकि यह उनके लिए पहले से प्रकाशित है। पहले log in करें, credential बदलें, फिर registration स्विच को बंद कर दें और यह पुष्टि करने के लिए page reload करें कि बदलाव लागू हो गया।

Step 04 · मापें

एक tag। फिर तय करें कि यह किसके domain पर रहेगा।

site को dashboard में register करें, इसके दिए हुए identifier को copy करें, और template में एक deferred script tag डाल दें — head में हो या body के आख़िर में, ज़्यादा फ़र्क़ नहीं पड़ता, मगर दोनों हाल में deferred हो ताकि यह page को कभी धीमा न करे। यही पूरा integration है। कोई tag manager नहीं, कोई container नहीं, कोई data layer नहीं और consent-mode की कोई wiring नहीं, और यही अनुपस्थिति दरअसल वह चीज़ है जिसके लिए आप यहाँ आए थे।

<script defer src="https://stats.example.com/script.js"
        data-website-id="00000000-0000-0000-0000-000000000000"></script>

site का एक page load करें, फिर dashboard देखें: hit कुछ सेकंड के भीतर वहाँ दिख जाना चाहिए। अगर नहीं दिखता, तो browser console और network tab एक मिनट के भीतर जवाब दे देते हैं — दो तरह की विफलताएँ होती हैं: एक गलत टाइप किया गया identifier, जिससे एक request बनती है जो accept होकर भी discard हो जाती है, और एक request जो कभी निकलती ही नहीं, जिसका मतलब है कि किसी extension ने उसे खा लिया। आँकड़े पढ़ना शुरू करने से पहले अपने खुद के traffic को exclude करें, नहीं तो आपके अपने reloads एक हफ़्ते तक आपके top referrer बने रहेंगे।

अब वह फ़ैसला जिसके बारे में सोचना ज़रूरी है। ऊपर वाला snippet एक ऐसे hostname पर request भेजता है जो site का अपना नहीं है, और आपके कुछ हिस्से visitors ऐसा software चलाते हैं जो ऐसी requests को pattern के आधार पर block कर देता है। ये lists जाने-पहचाने file names पकड़ लेती हैं — कोई भी नाम जो vendor के अपने script नाम पर ख़त्म होता है — और जाने-पहचाने hosted domains, चाहे वे किसी भी server की ओर इशारा करें। इसका इलाज दो हिस्सों में है: script file और collection endpoint का नाम बदल दें किसी ऐसी चीज़ में जो tracker जैसा नाम न हो, जिसे इनमें से हर tool समर्थन करता है, और उन्हें site के अपने origin से serve करें किसी ऐसे path के ज़रिए जिसे आपका मौजूदा proxy आगे भेज दे। इसके बाद block करने के लिए कोई third-party request बचती ही नहीं।

# On the site's own web server — the two paths the tracker needs, first-party:
example.com {
    handle /p/s.js      { reverse_proxy https://stats.example.com { header_up Host stats.example.com } }
    handle /p/collect   { reverse_proxy https://stats.example.com { header_up Host stats.example.com } }
    # ... the rest of the site
}

दो बारीकियाँ यह तय करती हैं कि यह पूरी तरह काम करे, आधा-अधूरा नहीं। proxy को visitor का address किसी ऐसे header में आगे भेजना ज़रूरी है जिस पर analytics application को भरोसा करने के लिए configure किया गया हो, नहीं तो हर hit आपके अपने web server के नाम दर्ज हो जाएगी और country report में सिर्फ़ एक ही bar बनेगा। और tracker को यह बताना ज़रूरी है कि उसका data कहाँ भेजना है, जो तीनों tools में script tag पर एक data attribute है — endpoint को दोबारा point किए बिना सिर्फ़ file का नाम बदल देने से आपके पास एक ऐसा script रह जाता है जो load तो होता है मगर कहीं report नहीं करता।

यही measurement की कहानी का ईमानदार अंत भी है। JavaScript बंद किए हुए visitor, या कोई strict list के साथ-साथ first-party cosmetic rule रखने वाला visitor, गिना नहीं जाएगा, और उसे पकड़ने में कोई भी इंजीनियरिंग ख़र्च नहीं करनी चाहिए — एक network-level filter एक जताई गई प्राथमिकता है, और इसका सलीकेदार जवाब है server log, जो उन्हें कुछ भी अतिरिक्त इकट्ठा किए बिना गिन लेता है। Events और single-page applications instrumentation का दूसरा आधा हिस्सा हैं: हर tool custom events के लिए एक छोटा function देता है, और इनमें से हर एक को route बदलने पर एक स्पष्ट call चाहिए, क्योंकि जो framework किसी navigation के बिना view बदल देता है, वह script के नोटिस करने के लिए कोई page load पैदा ही नहीं करता।

Step 05 · पालन करें

एक नहीं, दो कानून। इंटरनेट का ज़्यादातर हिस्सा इन्हें एक मान लेता है।

लोग इस बात पर सहमत नहीं हो पाते कि analytics को banner चाहिए या नहीं, इसकी वजह यह है कि वे दो अलग-अलग नियमों पर ऐसे बहस कर रहे होते हैं जैसे वे एक ही हों। उन्हें अलग कर दें तो जवाब समझ में आने लगता है। ePrivacy Directive का Article 5(3) — जिसे हर सदस्य-राष्ट्र ने अपने राष्ट्रीय कानून में उतारा है, और जो cookie banner का असली स्रोत है — कहता है कि किसी subscriber के terminal equipment पर जानकारी store करने, या उस पर पहले से store जानकारी तक पहुँच पाने के लिए उनकी सहमति चाहिए, सिवाय इसके कि यह उस service के लिए सख़्ती से ज़रूरी हो जिसकी उन्होंने स्पष्ट रूप से माँग की हो। ध्यान दें कि यह क्या नहीं कहता: यह cookie नहीं कहता, और यह personal data नहीं कहता। यह localStorage को पकड़ता है, यह device fingerprinting को पकड़ता है, और यह उस value पर भी लागू होता है जो किसी की भी पहचान नहीं बताती।

GDPR दूसरा नियम है और एक अलग सवाल तय करता है: personal data आपके हाथ में आने के बाद आप उसके साथ क्या कर सकते हैं। यह आपकी analytics पर तब भी लागू होता है जब आप device पर कुछ भी store न करें, क्योंकि एक web request एक IP address पहुँचाती है, और Court of Justice ने Breyer (C-582/14) में यह तय किया कि किसी website operator के हाथ में IP address personal data हो सकता है। इस तरह दोनों नियम एक-दूसरे पर टिके हैं: 5(3) पूछता है क्या आपने device पर कुछ लिखा, और GDPR पूछता है जो पहुँचा उसके साथ आपने क्या किया।

एक cookie-रहित analytics server दोनों सवालों का जवाब बहुत ही संकुचित दायरे में देने के लिए बनाया जाता है। यह device पर कुछ भी store नहीं करता — न cookie, न localStorage entry, न किसी तरह का identifier — जिससे 5(3) सिरे से बाहर हो जाता है, क्योंकि न कोई storage है, न storage तक कोई access। और यह जो IP address अनिवार्य रूप से प्राप्त होता है, उसे user agent, site, और हर दिन rotate होने वाले एक secret salt के साथ मिलाकर hash करता है, फिर hash रख लेता है और address हटा देता है। यह hash tool को एक दिन के भीतर दो visitors को अलग-अलग पहचानने देता है, और salt rotate होते ही यह बेकार हो जाता है — यही वजह है कि वही व्यक्ति अगले दिन एक नए visitor के रूप में गिना जाता है। यह processing असली है, और यह लगभग जितनी छोटी हो सकती है उतनी ही छोटी है।

जो बचता है वह उस संकुचित operation के लिए एक lawful basis है, और व्यवहार में operators Article 6(1)(f) के तहत legitimate interests पर निर्भर रहते हैं, जिसे एक balancing assessment के साथ दर्ज किया जाता है जो छोटा होता है क्योंकि तथ्य सीधे हैं: कोई profiling नहीं, कोई sharing नहीं, कोई cross-site tracking नहीं, हर दिन मरने वाला एक pseudonym, एक तय retention अवधि। कई supervisory authorities इससे भी आगे बढ़े हैं और ऐसे criteria प्रकाशित किए हैं जिनके तहत सख़्ती से सीमित audience measurement को सहमति से पूरी तरह exempt रखा जाता है — ये criteria देश के हिसाब से अलग हैं, इन्हें अपडेट किया जाता रहता है, और जो आपके लिए मायने रखता है वह आपका अपना ही है। यह legal advice नहीं है। यह इस बात का नक़्शा है कि कौन-से instruments लागू होते हैं, ताकि आप जो सलाह लें वह आपकी अपनी स्थिति के बारे में हो, न कि समस्या के सामान्य आकार के बारे में।

सवाल विज्ञापन-तकनीक analytics tag Cookie-रहित, EEA में self-hosted
visitor के device पर लिखता है?हाँ — इसलिए Article 5(3) वाली सहमति लागू होती हैनहीं — 5(3) trigger नहीं होता
क्या कोई स्थायी identifier रखा जाता है?sites के आर-पार, महीनों से सालों तकएक salted hash जो हर दिन expire हो जाता है
दर्ज करने योग्य कोई तीसरे-देश का transfer?हाँ, एक transfer mechanism बनाए रखने के साथकोई नहीं — box EEA में है
नाम व contract के साथ Processorsvendor और उसके subprocessorsआपका host, hardware के लिए, और कोई और नहीं
subject access request का जवाब कौन दे सकता हैआप, जो भी export मौजूद हो उसके ज़रिएआप, SQL के साथ — और अक्सर लौटाने के लिए कुछ भी नहीं होता

इस file में एक और पंक्ति की जगह बनती है, क्योंकि यही इस सबकी असली, ख़ामोश वजह है। यूरोपीय visitors का data किसी US analytics service को भेजने की क़ानूनी वैधता पर एक दशक से मुक़दमेबाज़ी चल रही है: Court of Justice ने 2020 में Schrems II (C-311/18) में पिछले transfer framework को रद्द कर दिया, कई राष्ट्रीय supervisory authorities ने 2022 में इसी आधार पर standard analytics tag के ख़िलाफ़ फ़ैसला दिया — जनवरी में Austria, फ़रवरी में France, जून में Italy, और उनके पीछे कुछ और भी — और एक नया adequacy decision, EU-US Data Privacy Framework, जुलाई 2023 में एक transfer रास्ता फिर से बहाल कर गया, और यह खुद भी चुनौती के दायरे में है। यह कैसे ख़त्म होगा, इस पर आपकी कोई राय होना ज़रूरी नहीं है। Helsinki में मौजूद एक box इस सवाल को आपकी file से हमेशा के लिए हटा देता है, और यह इस बात से कहीं ज़्यादा मूल्यवान है कि आप इसकी मौजूदा स्थिति को लेकर सही हों।

Step 06 · रखें

Retention, backups, upgrades। और वह log जिसे आप भूल गए।

retention अवधि पहले ही दिन तय कर लें, जब तक यह अब भी एक अमूर्त संख्या है, न कि उस एक साल के data जिससे आप जुड़ चुके हैं। इनमें से हर tool raw events को किसी schedule पर मिटा सकता है और summarised आँकड़े बचा सकता है; लगभग किसी भी मक़सद के लिए बारह महीनों का detail काफ़ी से ज़्यादा है, और इसका मतलब है कि "आप इसे कितने समय तक रखते हैं" का ईमानदार जवाब "अनिश्चित काल तक" के बजाय एक संख्या होता है। यह disk की समस्या को शुरू होने से पहले ही सुलझा देता है, जो Matomo के लिए सबसे ज़्यादा मायने रखता है, जिसकी raw tables ही बढ़ती हैं।

database को किसी ऐसी जगह backup करें जो यह machine न हो, और बाहर जाते समय उसे encrypt करें — पूरा विवरण backups गाइड में है, और संक्षेप में यह है: हर रात का एक dump किसी दूसरे box पर, आदर्श रूप से किसी दूसरे अधिकार-क्षेत्र में, एक append-only repository में pipe कर दिया जाए। इसके साथ application secret का भी backup रखें: जो database आप restore कर सकते हैं मगर जो secret नहीं कर सकते, वह एक ऐसा dashboard बन जाता है जिसमें कोई log in ही नहीं कर सकता। फिर ज़रूरत पड़ने से पहले, जान-बूझकर, इसे एक बार किसी scratch VPS पर restore करके देख लें।

docker compose exec -T db pg_dump -U umami umami | zstd -q -o /srv/backup/umami-$(date -u +%F).sql.zst
restic -r sftp:backup@bastion-2:/srv/repo backup /srv/backup /srv/analytics/.app_secret
restic -r sftp:backup@bastion-2:/srv/repo forget --keep-daily 7 --keep-weekly 8 --prune

Upgrades को एक सामान्य container bump से थोड़ी ज़्यादा सावधानी चाहिए, क्योंकि ये applications अपने-आप में एक schema रखते हैं। जिन major versions को आप पार कर रहे हैं उनके release notes पढ़ें, backup पहले लें न कि बाद में, फिर pinned tag बदलें और logs देखते हुए stack को ऊपर लाएँ — बीच में विफल हो जाने वाला एक migration पिछली रात के dump से ठीक किया जा सकता है, और उसके बिना यह बहुत अप्रिय होता है। किसी release के आने वाले हफ़्ते में ही सबसे नए release पर होने की कोई वजह नहीं है, और न होने की एक अच्छी वजह है।

वह log जो पूरी कसरत को बेकार कर देता है

आपने अभी-अभी एक ऐसा stack deploy किया है जो जान-बूझकर कभी कोई IP address store नहीं करता। दो मीटर दूर, आपका reverse proxy हर एक visitor का पूरा IP address एक access log में plain text में लिख रहा है, और इसे उतने समय तक रख रहा है जितना default rotation कहता है — दोनों जगह, analytics box पर भी और आपकी असली site के सामने खड़े web server पर भी। वह log analytics database से भी बड़ा और ज़्यादा संवेदनशील dataset है, यह एक processing operation है जिसका आपको हिसाब देना है, और लगभग कोई इसे याद नहीं रखता। तय करें कि यह किसलिए है: अगर यह सिर्फ़ debugging के लिए है, तो log format में आख़िरी octet को truncate या mask करें और तेज़ी से rotate करें; अगर आप इसे log-based measurement के लिए चाहते हैं, तो policy में यह बताएँ और इसे एक असली retention अवधि दें। जो आपको नहीं करना चाहिए वह है इसे default पर छोड़ देना और अपनी site के बारे में यह कहना कि वह IP addresses इकट्ठा नहीं करती।

आख़िर में, वे सीमाएँ जिनके बारे में ईमानदार होना ज़रूरी है, क्योंकि एक self-hosted counter उस चीज़ का सिर्फ़ एक बेहतर संस्करण नहीं है जिसे आपने हटाया। आप cross-device और cross-day identity खो देते हैं, इसलिए लौटता हुआ visitor पहले से कहीं संकुचित अर्थ रखने लगता है। आप ad-platform integration खो देते हैं, जो तब मायने रखता है जब आप traffic ख़रीदते हैं, और तब बेमानी है जब आप नहीं ख़रीदते — search console का data एक अलग product है और इससे अप्रभावित रहता है। आपको एक upgrade और एक backup का ज़िम्मा लेना पड़ता है, जो शामों में नापी जाने वाली एक वास्तविक, बार-बार आने वाली लागत है। और box अपने-आप में एक ऐसी चीज़ बन जाता है जिसकी रक्षा करने लायक है: यह आपके पाठकों को थामे रखता है, यह public internet पर है, और hardening checklist तथा dashboard तक का private रास्ता — यही दो चीज़ें हैं जो इसे उबाऊ बनाए रखती हैं।

Field notes · छह traps

छह तरीके जिनसे यह गड़बड़ हो सकता है। इनमें से दो ख़ामोश हैं।

Trap 01 · घातक

वह default password जो सब जानते हैं

इनमें से एक tool धरती की हर installation पर एक जैसा ही administrator credential देकर आता है; बाक़ी जो भी पहले register करे उसे ownership थमा देते हैं। TLS काम करना शुरू करते ही hostname certificate transparency logs में प्रकाशित हो जाता है। log in करें, इसे बदलें, registration बंद करें — पहले पाँच मिनट में, कल नहीं।

Trap 02 · घातक

tutorial वाला database port

laptop के लिए लिखी गई Compose files 5432 या 3306 publish करती हैं ताकि author किसी GUI से connect कर सके। ऐसी ही किसी file को किसी public box पर copy कर दें, तो पाठकों वाली table सिर्फ़ एक password-guess जितनी दूर रह जाती है। application container database तक internal network के ज़रिए पहुँचता है; proxy के अलावा कुछ भी publish करने की ज़रूरत नहीं है।

Trap 03 · कानूनी

यह मान लेना कि self-hosted होना ही exempt होने के बराबर है

software को अपने ही box पर ले जाना transfer वाले सवाल और processor वाले सवाल का जवाब दे देता है। मगर अगर आप फिर कोई ऐसा feature चालू कर दें जो device पर कुछ लिखता है, तो यह Article 5(3) का जवाब नहीं देता, और यह आपकी privacy policy भी नहीं लिखता। exemption configuration का गुण है, hosting का नहीं।

Trap 04 · ख़ामोश

हर visitor एक ही देश से आता है

एक reverse proxy जो client address forward नहीं करता, हर hit को ऐसा दिखा देता है जैसे वह proxy से ही आया हो। dashboard भरता जाता है, totals सही दिखते हैं, लेकिन geography और uniqueness वाले columns चुपचाप कल्पना बनकर रह जाते हैं। country breakdown पहले ही दिन जाँच लें, quarterly review में नहीं।

Trap 05 · ख़ामोश

वह access log जो आप अब भी रख रहे हैं

यह stack इसलिए चुना गया था क्योंकि यह कभी कोई IP address store नहीं करता। इसके सामने खड़ा proxy डिफ़ॉल्ट रूप से उनमें से हर एक को plain text में store करता है, और आपकी असली site के सामने खड़ा web server भी ऐसा ही करता है। उन्हें जान-बूझकर mask या rotate करें, और policy में उनका ज़िक्र करें — या फिर यह दावा करना बंद करें कि आप उन्हें इकट्ठा नहीं करते।

Trap 06 · टालने योग्य

पुराने आँकड़ों के पीछे भागना

नए totals पुराने से मेल नहीं खाएँगे, और कोई configuration उन्हें मिला नहीं सकती। अलग counting rules, block होने वाला एक अलग हिस्सा, और sample को filter करने वाला कोई banner नहीं। वह दो हफ़्ते अपना ratio जानने में लगाएँ, फिर नए आँकड़े को ही baseline मानें और दो definitions को मिलाने की कोशिश बंद कर दें।

सामान्य प्रश्न · Self-hosted Analytics

प्रश्न, उत्तरित।

ग्यारह सवाल जो यह करते समय सामने आते हैं — शुरुआत उस सवाल से जिसे लगभग सभी दोनों दिशाओं में गलत समझते हैं।

अगर मैं self-host करूँ तो क्या मैं सचमुच cookie banner हटा सकता हूँ?

अक्सर हाँ, और इसकी वजह "self-hosted होना ही ठीक है" से कहीं ज़्यादा सटीक है। यहाँ दो अलग-अलग नियम काम कर रहे हैं। ePrivacy Directive का Article 5(3) — जिसे सब cookie कानून कहते हैं — किसी visitor के device पर जानकारी store करने, या उससे जानकारी पढ़ने के लिए सहमति की मांग करता है, सिवाय इसके कि यह उस service के लिए सख़्ती से ज़रूरी हो जिसकी उन्होंने माँग की थी। यह cookies पर लागू होता है, मगर localStorage, sessionStorage और आपके छोड़े गए किसी भी और चीज़ पर भी, और यह लागू होता है चाहे data personal हो या न हो। जो tool device पर कुछ भी नहीं लिखता, वह इसे सिरे से trigger ही नहीं करता। GDPR दूसरा नियम है और यह कहीं नहीं जाता: हर request पर आपको फिर भी एक IP address और एक user-agent string मिलती है, और किसी website operator के हाथ में IP address personal data होता है (Court of Justice, Breyer, C-582/14)। एक cookie-रहित analytics server जो करता है वह यह है कि वह उस IP को हर दिन rotate होने वाले salt से hash करता है और फिर उसे हटा देता है, इसलिए database में जो पहुँचता है वह किसी व्यक्ति के बजाय एक प्रति-दिन, प्रति-site pseudonym है। यह एक संकुचित, अच्छी तरह दर्ज़ processing operation है जिस पर ज़्यादातर operators legitimate interests के आधार पर टिके रहते हैं, और कई supervisory authorities ने ऐसे criteria प्रकाशित किए हैं जिनके तहत सिर्फ़ audience measurement को सहमति से exempt रखा जाता है। यह एक defensible स्थिति है, कोई जादुई शब्द नहीं: लिख लें कि आप क्या इकट्ठा करते हैं, क्यों, और कितने समय के लिए, और किसी vendor के landing page के बजाय अपने ही regulator की guidance पढ़ें। इस page पर कुछ भी legal advice नहीं है।

अगर मैं इस पर सोचना ही नहीं चाहूँ, तो मुझे कौन-सा चुनना चाहिए?

Umami। यह एक ही Node application और एक PostgreSQL database है, यह 1 GB memory के भीतर सहज रहता है, dashboard पहली ही visit पर समझ में आ जाता है, यह शुरू से ही cookie-रहित है, और एक instance आपकी हर site को ख़ुशी-ख़ुशी सेवा देता है। Google Analytics को किसी blog, documentation site, shop या company site पर बदलने वाले भारी बहुमत लोगों के लिए, यही सही जवाब है, और बाक़ी तीन एक ऐसी बहस हैं जिसकी आपको ज़रूरत ही नहीं थी। इसके बजाय Plausible Community Edition चुनें अगर आपको funnels, revenue goals और एक ज़्यादा मज़बूत public-dashboard कहानी चाहिए और आप उनके लिए ClickHouse चलाने को तैयार हैं। Matomo चुनें अगर आपको सचमुच Google Analytics वाला feature सेट चाहिए — segments, cohorts, custom reports, e-commerce attribution, raw log import — और आप यह मानने को तैयार हैं कि आप एक scheduled archiving job वाला बड़ा PHP application चला रहे हैं। GoAccess चुनें अगर आपको page पर बिल्कुल कोई JavaScript नहीं चाहिए।

आँकड़े Google Analytics से मेल क्यों नहीं खाते?

क्योंकि वे अलग-अलग चीज़ें गिन रहे होते हैं, और यह अंतर एक साथ दोनों दिशाओं में चलता है। ऊपर की ओर: सहमति banner के पीछे बैठा Google Analytics सिर्फ़ उन्हीं visitors को देखता है जिन्होंने accept दबाया, जो यूरोप में आम तौर पर उनमें से आधे ही होते हैं, जबकि banner-रहित cookie-रहित counter सबको देखता है। फिर ऊपर की ओर: आपका नया endpoint आपके अपने domain पर है और उन filter lists में शामिल नहीं है जो जाने-पहचाने trackers की requests को छोड़ देती हैं। नीचे की ओर: रोज़ाना rotate होने वाला hash कल उसी व्यक्ति को नहीं पहचान सकता, इसलिए सोमवार और गुरुवार को आने वाला एक reader एक लौटता हुआ visitor नहीं, बल्कि दो अलग visitors गिना जाता है — sessions एक दिन के भीतर तो जुड़ते हैं, मगर दिनों या devices के आर-पार कभी नहीं। फिर नीचे की ओर: ज़्यादातर self-hosted tools एक conservative bot filter के साथ आते हैं और उनमें Discover-जैसी कोई inflation नहीं होती। असली सलाह यह है कि मिलान करना बंद कर दें। दो हफ़्तों तक दोनों को साथ चलाएँ, अपना खुद का ratio जान लें, उसे किसी sticky note पर लिख लें, फिर Google tag हटा दें और नए आँकड़ों को उस baseline के रूप में इस्तेमाल करें जो अब वे बन चुके हैं। फ़ैसलों के लिए जो चीज़ मायने रखती है वह है trend का आकार और pages और sources की सापेक्ष रैंकिंग, और यह बदलाव दोनों को बिना किसी नुक़सान के बचा लेता है।

क्या ad blockers मेरे अपने instance को भी block करेंगे?

आंशिक रूप से, और यह ठीक-ठीक जानना ज़रूरी है कि कैसे, क्योंकि यह mechanism लोगों की सोच से कहीं ज़्यादा भोंडा है। बड़ी filter lists patterns पर काम करती हैं: hosted services के hostnames, और मशहूर file व path नामों का एक समूह — plausible.js, umami.js या matomo.php पर ख़त्म होने वाली किसी भी चीज़ के लिए request पहचानी जा सकती है, चाहे वह किसी भी server तक जाए। software को stats.example.com पर ले जाएँ और स्टॉक file नामों के साथ रखें, तो भी आप technical audience का एक हिस्सा खो देंगे। इसके दो ईमानदार इलाज हैं, और वे साथ मिलकर काम करते हैं। script और collection endpoint का नाम बदलकर कोई ऐसा नाम रखें जो tracker जैसा न लगे — इनमें से हर tool आपको यह करने देता है, और इसमें configuration की सिर्फ़ एक पंक्ति ख़र्च होती है। इन्हें site के अपने origin से ही serve करें, अपने main domain के किसी ऐसे path के ज़रिए जिसे reverse proxy आगे भेज देता है, ताकि block करने के लिए कोई third-party request बचे ही नहीं। दोनों मिलकर आप ज़्यादातर नुक़सान वापस पा लेते हैं। पूरा नुक़सान आप वापस नहीं पाएँगे, और आपको चाहना भी नहीं चाहिए: जो visitor एक strict list के साथ-साथ JavaScript भी बंद रखता है, उसने एक चुनाव किया है, और इसका सही जवाब server log है, कोई हथियारों की दौड़ नहीं।

क्या script को अपने ही domain के ज़रिए proxy करना एक dark pattern है?

यह सवाल पूछे जाने लायक है, और इसका जवाब इस पर निर्भर करता है कि blocker असल में किसकी रक्षा कर रहा था। एक filter list के पास एक ही मोटा-सा tool है और दो बहुत अलग निशाने: वह ad-tech network जो किसी व्यक्ति का दस हज़ार sites तक पीछा करता है और एक profile बनाता है, और वह counter जो किसी एक site के मालिक को बताता है कि उसका documentation page कल चार सौ बार पढ़ा गया। पहले को block करना एक व्यक्ति द्वारा surveillance से खुद को बचाना है। दूसरे को block करना एक ऐसे नियम से हुआ collateral damage है जो दोनों में फ़र्क़ नहीं कर सकता। अपने counter को अपने ही domain से serve करना किसी defence से चोरी-छुपे tracker निकालना नहीं है; यह एक ऐसा third-party request हटाना है जिसे कभी होना ही नहीं चाहिए था, और वही visit फिर भी आपके access log में एक पंक्ति बना देती है। यह justify होना बंद तभी करता है जब आप जो proxy कर रहे हैं वह वह चीज़ न रहे जो यहाँ बताई गई है — अगर आप cross-site identifiers, fingerprinting, या किसी ad platform की ओर जाने वाला pipeline जोड़ दें, तो blocker सही था और proxy एक झूठ है। यह जाँच सरल है और खुद पर एक बार लागू करने लायक है: क्या आप एक page प्रकाशित कर सकते हैं जो ठीक-ठीक बताए कि यह endpoint क्या इकट्ठा करता है, और क्या कोई reader उसे पढ़कर बस कंधे उचकाएगा? यदि हाँ, तो इसे proxy करें। यदि नहीं, तो समस्या proxy नहीं है।

VPS को असल में कितना बड़ा होना चाहिए?

जितना आपको डर है उससे छोटा, एक अपवाद के साथ। Umami एक Node process और एक Postgres database है: यह किसी सामान्य site के लिए 1 GB memory से नीचे ही टिक जाता है, और database हर pageview पर लगभग एक text line जितना बढ़ता है, इसलिए एक Sentinel — 2 vCPU, 4 GB, 120 GB NVMe, $3.90 प्रति माह — के पास बरसों की गुंजाइश है। GoAccess एक rounding error जैसा है। Matomo बीच में आता है: PHP और MariaDB तब तक हल्के रहते हैं जब तक archiving job नहीं चलता, जो वह CPU spike है जिसके हिसाब से आपको size तय करनी पड़ती है, और इसकी raw tables बाक़ियों से तेज़ी से बढ़ती हैं क्योंकि यह हर hit पर ज़्यादा रखता है। अपवाद है Plausible Community Edition, और इसकी वजह Plausible नहीं बल्कि ClickHouse है: एक column store memory को query की रफ़्तार से बदलने के लिए बना है और आपने जो भी छोड़ रखा है उसे इस्तेमाल कर लेगा। अगर आप shipped configuration में इसके caches की सीमा तय कर दें तो यह 4 GB में चल जाता है, और यह 8 GB पर सहज रहता है — यही वजह है कि $7.90 वाला Garrison tier इसके लिए उचित न्यूनतम है। हर हाल में, जो संख्या आख़िरकार upgrade करने पर मजबूर करती है वह disk है, memory नहीं, और step 06 यही बताता है कि इसे कैसे रोकें।

क्या एक ही instance कई अलग-अलग sites को measure कर सकता है?

हाँ, और यही इन्हें चलाने का सामान्य तरीक़ा है। तीनों JavaScript tools डिज़ाइन से ही multi-site हैं: आप dashboard में हर domain register करते हैं, हर एक को अपना identifier मिलता है, और एक ही script endpoint सबके लिए hits स्वीकार करता है जबकि reports अलग-अलग रहती हैं। एक box, एक certificate, एक backup, एक upgrade — बीस sites। जैसे-जैसे सूची बढ़े, दो बातें याद रखने लायक हैं। reports site के हिसाब से अलग रहती हैं, इसलिए अगर आप clients के लिए sites प्रशासित करते हैं, तो सबको administrator account थमाने के बजाय tool के अपने user और team permissions इस्तेमाल करें, और किसी shared instance का मतलब क्या है यह जाँच लें इससे पहले कि आप इसे किसी contract में मान लें: आप उनके visitors का data थामने वाला पक्ष बन जाते हैं। और tracking endpoint एक साझा नाम है, जिसका मतलब है कि जो domain इसे serve करता है वह सूची की हर site के source में दिखता है — यह एक ऐसा तथ्य है जिसका ज़िक्र किसी ऐसे client से करना ज़रूरी है जिसके प्रतिस्पर्धी page source पढ़ते हैं, और यह step 04 वाले first-party रास्ते के लिए एक दलील भी है।

क्या मुझे JavaScript की ज़रूरत भी है? server log का विश्लेषण करने के बारे में क्या?

sites की एक बड़ी श्रेणी के लिए, log ही काफ़ी है, और यह उपलब्ध सबसे ईमानदार measurement है: यह कुछ भी अतिरिक्त इकट्ठा नहीं करता, क्योंकि ये पंक्तियाँ पहले से मौजूद हैं। GoAccess एक web server access log पढ़ता है और एक terminal report या एक self-contained HTML dashboard बनाता है — top pages, referrers, status codes, bandwidth, response times, user agents — किसी static site, किसी documentation सेट या किसी API के लिए, यही ज़्यादातर वह है जो एक script tag आपको बताने वाला था। दो सीमाएँ तय करती हैं कि यह आपके लिए काफ़ी है या नहीं। कोई log page के भीतर होने वाली गतिविधि नहीं देख सकता: न scroll depth, न outbound-link clicks, न button events, न single-page-application route बदलाव, क्योंकि इनमें से कोई भी server को छूता ही नहीं। और एक log requests गिनता है, लोगों को नहीं, इसलिए आप caching और bot आबादी की दया पर रहते हैं जो अब raw traffic का बहुमत बन चुकी है — filtering एक स्थायी maintenance काम है, कोई एक बार का setup चरण नहीं। इसके अलावा एक privacy trap उस दिशा से उल्टी दिशा में भी है जिसकी आपको आशंका होगी, और step 06 इसे कवर करता है: जिस log का आप विश्लेषण कर रहे हैं उसमें पूरे IP addresses मौजूद हैं, जो उस JavaScript tool से भी ज़्यादा personal data है जिसे आपने ठुकराया था।

क्या मैं अपनी Google Analytics history import कर सकता हूँ?

व्यावहारिक रूप से, नहीं, और इसे लेकर लड़ने के बजाय इसकी योजना बना लेना बेहतर है। चारों में से सिर्फ़ Matomo के पास कोई गंभीर import रास्ता है, और वहाँ भी व्यावहारिक तरीके हैं अपने web server logs import करना और पुराने Matomo instances के लिए migration tooling इस्तेमाल करना, न कि Google की processed reports का कोई साफ़-सुथरा transfer। Umami और Plausible Community Edition अपने APIs के ज़रिए bulk load स्वीकार कर सकते हैं, अगर आप mapping खुद लिखने को तैयार हैं, मगर आप aggregated exports से sessions और visitors गढ़ रहे होंगे, और नतीजा एक ऐसा chart होगा जो लगातार दिखता है मगर उस जोड़ के आर-पार तुलना करने लायक नहीं है। जो असल में काम करता है वह यह है: property ख़त्म होने से पहले Google से वे reports export कर लें जो आपके लिए मायने रखती हैं — मासिक totals, top pages, top sources, conversion counts — CSV के रूप में, उन्हें अपने बाकी records के साथ ही रखें, और नए tool को किसी लिखी हुई तारीख़ पर एक नए baseline के तौर पर शुरू करें। आप पुराने export से पहले साल में दो बार सलाह लेंगे और फिर कभी नहीं, और उसमें मौजूद हर संख्या वैसे भी एक अलग definition के तहत मापी गई थी।

मुझे privacy policy में असल में क्या लिखना होगा?

जितना आप सोचते हैं उससे कम, और यह छोटा होना ही मुख्य बात है — एक ऐसा paragraph जिसका आप बचाव कर सकें, कहीं से copy किए गए एक पूरे page से बेहतर है। बताएँ कि tool क्या है और यह कि आप इसे खुद चलाते हैं; server की location और legal operator का नाम बताएँ, क्योंकि यह कह पाना कि "हम जो machine किराए पर लेते हैं वह Finland में है" ही इस पूरी कसरत का असली फ़ायदा है। बताएँ कि हर visit पर क्या दर्ज होता है: page, referrer, देश, device और browser की family, और IP address व user agent से, हर दिन बदलने वाले एक salt के साथ, निकाला गया एक pseudonymous identifier, जिससे मूल IP दोबारा हासिल नहीं किया जा सकता। बताएँ कि क्या दर्ज नहीं होता: कोई cookie नहीं, कोई cross-site identifier नहीं, कोई profile नहीं, कोई data बेचा या साझा नहीं किया जाता। जिस lawful basis पर आप निर्भर हैं और retention अवधि, दोनों बताएँ, और सुनिश्चित करें कि जो संख्या आप लिखें वही हो जो tool में configure की गई है। अगर आपका reverse proxy access logs रखता है, तो वह एक अलग processing operation है जिसकी अपनी retention है — इसका ज़िक्र करें, क्योंकि यही वह चीज़ है जिसे लोग भूल जाते हैं। फिर paragraph को configuration के साथ मिलाकर रखें: ऐसी policy जो दो साल पहले वाला setup बताती हो, एक अस्पष्ट policy से भी बदतर है।

जो box सिर्फ़ page views रखता है, उसके लिए host क्यों मायने रखता है?

क्योंकि "सिर्फ़ page views" कहना यह कम करके बताता है कि एक analytics database असल में क्या होता है। एक साल में जोड़ने पर, यह आपकी site के पाठकों का पूरा ब्योरा बन जाता है: कौन-से pages, किस क्रम में, किन देशों से, किन घंटों में, किन links से आते हुए — और किसी छोटे publisher या niche shop के लिए, यह एक ही table में समाया हुआ एक business plan और एक source list है। यह, अधिकार-क्षेत्र की दृष्टि से भी, ठीक वैसा ही data है जिसे कोई adversary आपसे पूछने के बजाय किसी provider से माँगता है। इससे दो बातें निकलती हैं। box कहाँ रखा है, यह तय करता है कि कौन-सी legal process उस तक पहुँच सकती है: Stockholm, Helsinki, Oslo या Reykjavík में मौजूद कोई machine EEA के भीतर आती है, जिससे international-transfer वाला सवाल आपकी compliance file से पूरी तरह हट जाता है, और यह प्रेस-स्वतंत्रता की मज़बूत परंपरा वाली चार संवैधानिक व्यवस्थाओं के भीतर भी आती है। और account पर किसका नाम है, यह तय करता है कि account खुद क्या ज़ाहिर करता है: NordBastion पर कोई पहचान-दस्तावेज़ नहीं है, कोई legal name नहीं, कोई card नहीं, invoice Monero या Bitcoin में चुकता होता है, और आपके पाठकों को थामे हुए machine कहीं किसी customer database की वह पंक्ति नहीं है जिसके साथ आपका passport जुड़ा हो। jurisdiction गाइड इन चारों में से हर एक के legal आधार को विस्तार से बताती है।

box लें

आपके पाठक, EEA में मौजूद एक ऐसी machine पर जो आपके नाम पर registered नहीं है।

Sentinel — Helsinki, Stockholm, Oslo या Reykjavík में, $3.90 प्रति माह पर 2 vCPU, 4 GB और 120 GB NVMe — Umami और उसके database को बरसों के events की गुंजाइश के साथ चला देता है। अगर आपने Plausible या Matomo चुना है तो $7.90 पर Garrison पर चले जाएँ। signup पर कोई email नहीं, कोई पहचान-दस्तावेज़ नहीं, कोई card नहीं, और कोई तीसरा पक्ष नहीं जो उन सबकी सूची थामे रखे जिन्होंने कभी आपकी site पढ़ी हो।

अंतिम review · 2026-10-12 · स्रोत · Umami, Plausible Community Edition, Matomo और GoAccess का documentation; ePrivacy Directive 2002/58/EC का Article 5(3); Regulation (EU) 2016/679; Breyer (C-582/14) और Schrems II (C-311/18) में Court of Justice के फ़ैसले; जुलाई 2023 का EU-US Data Privacy Framework adequacy decision · आवृत्ति · वार्षिक

निजी होस्टिंग, उत्तर में निर्मित।