fix(analitik): görünüm hook'u callback ref + erken olay kuyruğu
useGorunumOlayi useRef + [ad, anahtarEki] deps'li effect kullanıyordu:
eleman ilk commit'te yoksa (kaydet-banner: mount sonrası açılır, portal
içinde) ya da sökülüp yeni düğümle geri geliyorsa (tadımlık satırı) gözlem
hiç kurulmuyordu → kaydet_banner_goruntulendi / tadimlik_goruntulendi = 0.
Hook artık callback ref döner; gözlem düğüm bağlanınca kurulur, sökülünce
React 19 ref temizliğiyle bırakılır. Çağıranlar yalnız ref={…} verdiği
için kullanım yerleri değişmedi.
olay(): Rybbit script'i afterInteractive; sert yüklemede mount anında
atılan olaylar window.rybbit henüz yokken sessizce düşüyordu. Artık en çok
20 olay, 500 ms aralıkla en çok 20 deneme (10 sn) kuyrukta bekler; script
gelmezse (reklam engelleyici, dev) kuyruk atılır.
olayBirKez(): hook'taki sessionStorage tekilleştirmesinin effect'ten
çağrılabilir hâli (anahtar biçimi aynı: kolaytercih.olay.<ad>[.<ek>]).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,54 +1,60 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, type RefObject } from "react";
|
||||
import { olay, type OlayAdi, type Ozellikler } from "@/lib/analitik";
|
||||
import { useCallback, useEffect, useRef, type RefCallback } from "react";
|
||||
import {
|
||||
olayAnahtari,
|
||||
olayBirKez,
|
||||
type OlayAdi,
|
||||
type Ozellikler,
|
||||
} from "@/lib/analitik";
|
||||
|
||||
/**
|
||||
* Bir elemanın viewport'a ilk girişinde analitik olayı atan ref hook'u.
|
||||
* Gösterim olayları (hazir_panel_goruntulendi, kilit_goruntulendi vb.)
|
||||
* oturum başına en fazla 1 kez sayılmalı; tekilleştirme sessionStorage
|
||||
* anahtarıyla yapılır. IntersectionObserver yoksa olay hiç atılmaz —
|
||||
* "görüntülendi" ölçümünde görünürlüğü doğrulayamadığımız cihazı saymak
|
||||
* veriyi şişirir.
|
||||
* anahtarıyla yapılır (bkz. olayBirKez). IntersectionObserver yoksa olay hiç
|
||||
* atılmaz — "görüntülendi" ölçümünde görünürlüğü doğrulayamadığımız cihazı
|
||||
* saymak veriyi şişirir.
|
||||
*
|
||||
* Callback ref döner (RefObject değil): gözlem effect'te değil, DOM düğümü
|
||||
* bağlandığı anda kurulur. Eleman ilk commit'te yoksa (kaydet-banner: mount
|
||||
* sonrası açılır, üstelik portal içinde) ya da sökülüp yeni bir düğümle geri
|
||||
* geliyorsa (tadımlık satırı: tip uymayınca gizlenip fetch sonrası yeniden
|
||||
* takılır) useRef + effect deseni gözlemi hiç kurmuyordu.
|
||||
*/
|
||||
export function useGorunumOlayi<T extends HTMLElement = HTMLElement>(
|
||||
ad: OlayAdi,
|
||||
ozellikler?: Ozellikler,
|
||||
/** Aynı olayın farklı yüzeyleri için tekilleştirme eki ("satir", "kart"). */
|
||||
anahtarEki?: string,
|
||||
): RefObject<T | null> {
|
||||
const ref = useRef<T>(null);
|
||||
// Özellikler her render sonrası tazelenir; observer effect'i yalnızca
|
||||
// ad/anahtar değişiminde kurulur (deps'e obje koymamak için ref).
|
||||
): RefCallback<T> {
|
||||
// Özellikler her render sonrası tazelenir; callback ref yalnızca ad/anahtar
|
||||
// değişiminde yeniden kurulur (deps'e obje koymamak için ref).
|
||||
const ozelliklerRef = useRef(ozellikler);
|
||||
useEffect(() => {
|
||||
ozelliklerRef.current = ozellikler;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el || typeof IntersectionObserver === "undefined") return;
|
||||
return useCallback(
|
||||
(el: T | null) => {
|
||||
if (!el || typeof IntersectionObserver === "undefined") return;
|
||||
|
||||
const anahtar = `kolaytercih.olay.${ad}${anahtarEki ? `.${anahtarEki}` : ""}`;
|
||||
try {
|
||||
if (window.sessionStorage.getItem(anahtar)) return;
|
||||
} catch {
|
||||
// Storage engelliyse tekilleştirmeden vazgeç, olay yine atılabilir
|
||||
}
|
||||
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
if (!entries.some((e) => e.isIntersecting)) return;
|
||||
io.disconnect();
|
||||
try {
|
||||
window.sessionStorage.setItem(anahtar, "1");
|
||||
if (window.sessionStorage.getItem(olayAnahtari(ad, anahtarEki))) return;
|
||||
} catch {
|
||||
// yut
|
||||
// Storage engelliyse tekilleştirmeden vazgeç, olay yine atılabilir
|
||||
}
|
||||
olay(ad, ozelliklerRef.current);
|
||||
});
|
||||
io.observe(el);
|
||||
return () => io.disconnect();
|
||||
}, [ad, anahtarEki]);
|
||||
|
||||
return ref;
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
if (!entries.some((e) => e.isIntersecting)) return;
|
||||
io.disconnect();
|
||||
olayBirKez(ad, ozelliklerRef.current, anahtarEki);
|
||||
});
|
||||
io.observe(el);
|
||||
// React 19 ref temizliği: düğüm sökülünce (ya da ad/anahtar değişince)
|
||||
// gözlemci bırakılır; yeni düğüm bağlanınca callback baştan çalışır.
|
||||
return () => io.disconnect();
|
||||
},
|
||||
[ad, anahtarEki],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user