← العودة إلى المدونة

إضافة تحليلات تركز على الخصوصية إلى تطبيق SvelteKit

يعترض SvelteKit 2 التنقل من جانب العميل بشكل مختلف عن أطر العمل الأخرى. إليك النمط الصحيح لتتبع تغييرات المسار دون كوكيز أو لافتة موافقة.

يكسر SvelteKit 2 تكاملات التحليلات التي تُعلِّق القياس على دورة حياة الصفحة. فوسم <script> البسيط يُطلَق مرة واحدة فقط، عند أول تحميل للمستند، ولا يُطلَق بعدها أبداً — ومن ثمَّ يصبح كل تنقل لاحق من جانب العميل غير مرئي. يتفادى متعقب Monoid ذلك بمراقبة History API بدلاً من دورة حياة الصفحة.

لماذا لا يكفي وسم script بسيط

يُنفَّذ وسم <script> داخل <svelte:head> مرة واحدة لكل تحميل للمستند. وموجِّه SvelteKit 2 يستبدل المحتوى في مكانه دون تفريغ المستند، فلا شيء يُعيد تنفيذه. وأي متعقب يكون مُطلِقه الوحيد DOMContentLoaded أو load سيُبلِّغ عن مسار الدخول ثم يصمت.

هذا هو السبب الجذري للمشكلة المُبلَّغ عنها على نطاق واسع حيث يسجل Google Analytics GA4 المشاهدة الأولى فقط عند التحميل الأولي في تطبيقات SvelteKit 2.

الحل هو رصد التنقل نفسه، وهذا لا يستلزم تكاملاً خاصاً بـ SvelteKit. فموجِّه SvelteKit من جانب العميل يُحدِّث عنوان URL باستدعاء history.pushState، ولذلك فإن متعقباً يُرقِّع history.pushState يرصد كل تغيير مسار من جانب العميل دون الاشتراك في $app/navigation ولا في أي خطاف من خطافات إطار العمل.

النهج الصحيح

أضف سكربت متعقب Monoid مرة واحدة إلى +layout.svelte الجذري باستخدام <svelte:head>:

<svelte:head>
  <script
    async
    src="https://api.monoid.website/tracker.min.js"
    data-site-id="YOUR_SITE_ID"
  ></script>
</svelte:head>

يُغطي مستمع DOMContentLoaded في المتعقب التحميل الأولي للصفحة. أما في التنقلات اللاحقة من جانب العميل، فيعمل ترقيعه لـ history.pushState مباشرةً بعد أن يُحدِّث SvelteKit عنوان URL، فيقرأ location.pathname الجديد ويُرسل مشاهدة صفحة واحدة لكل تغيير مسار.

تحذير جدير بالمعرفة: يغطي الترقيع pushState وليس popstate. فزرّا الرجوع والتقدم يُغيِّران المسار دون استدعاء pushState، ولذلك لا يُنتِجان حالياً مشاهدة صفحة جديدة.

للتحقق، افتح علامة تبويب Network في DevTools وراقب طلبات POST إلى /collect. يجب أن ترى واحداً لكل تغيير مسار.

فصل حركة المرور التجريبية

تعمل مشاريع SvelteKit عادةً على localhost أثناء التطوير. سجل موقعاً منفصلاً واربط site_id الخاص به بمتغير بيئة حتى لا تلوث حركة المرور التطويرية مقاييس الإنتاج:

<script>
  const siteId = import.meta.env.VITE_MONOID_SITE_ID
</script>

<svelte:head>
  {#if siteId}
    <script
      async
      src="https://api.monoid.website/tracker.min.js"
      data-site-id={siteId}
    ></script>
  {/if}
</svelte:head>

عيّن VITE_MONOID_SITE_ID في .env.local للتطوير (أو اتركه غير معيّن لمنع التتبع) وفي بيئة النشر للإنتاج. تضمن كتلة {#if siteId} أن المتعقب لن يُحقن أبداً عندما لا يكون المتغير معيناً.

ما لا تحتاجه

لا لافتة موافقة كوكيز. لا تحديث لسياسة الكوكيز. لا فحص navigator.cookieEnabled. تشتق نقطة نهاية التجميع تجزئة زائر يومية من عنوان IP وUser-Agent ومفتاح سري من جانب الخادم والتاريخ الحالي:

visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)

تُعاد التجزئة كل 24 ساعة ولا يمكن عكسها لاسترداد IP أو User-Agent. لا يُخزَّن شيء على جهاز الزائر. هذا يعني أن التكامل لا يُفعّل متطلبات موافقة ePrivacy أو PECR، لا يوجد شيء للموافقة عليه.

التحقق في لوحة التحكم

بعد النشر، افتح لوحة تحكم التحليلات وانتقل بين عدة مسارات على موقعك المباشر. يجب أن يُنتج كل تنقل إدخال مشاهدة صفحة جديد بالمسار الصحيح. إذا رأيت إدخالاً واحداً فقط بغض النظر عن التنقل، تحقق من أن السكربت محمَّل في التخطيط الجذري وأن VITE_MONOID_SITE_ID معيّن في بيئة الإنتاج.

محوّل SvelteKit الذي تستخدمه (Cloudflare، Vercel، Node، static) لا يؤثر على جمع التحليلات، حيث يحدث التتبع بالكامل في المتصفح بعد الترطيب (hydration).

المصادر

Comments

Loading comments…