fix(analitik): kullaniciTanit script'ten önce sessiz no-op olmasın
Erken olay kuyruğu yalnız olay() içindi; sert yüklemede (OAuth / e-posta linki dönüşü) RybbitIdentify effect'i de script'ten önce koşuyor, identify kayboluyor ve kuyruktan boşalan olaylar anonim profile yazılıyordu (08-kod-denetimi #6). - Tek "son değer" slotu (bekleyenKimlik): kuyruk değil, yalnız en son kimlik anlamlı. Yoklama zamanlayıcısı olay kuyruğuyla ortak (zamanlayiciyiBaslat); script 10 sn'de gelmezse slot da atılır. - kuyruguBosalt kimliği olaylardan ÖNCE uygular. - kullaniciTemizle slotu siler. rybbit-identify.tsx'e dokunulmadı. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,10 @@ const DENEME_ARALIGI_MS = 500;
|
|||||||
const DENEME_SINIRI = 20;
|
const DENEME_SINIRI = 20;
|
||||||
|
|
||||||
let kuyruk: Array<[OlayAdi, Ozellikler | undefined]> = [];
|
let kuyruk: Array<[OlayAdi, Ozellikler | undefined]> = [];
|
||||||
|
// Script'ten önce gelen identify için tek "son değer" slotu: sert yüklemede
|
||||||
|
// (OAuth / e-posta linki dönüşü) RybbitIdentify effect'i de script'ten önce
|
||||||
|
// koşar. Kuyruk değil slot — yalnız en son kimlik anlamlıdır.
|
||||||
|
let bekleyenKimlik: [string, Record<string, string> | undefined] | null = null;
|
||||||
let zamanlayici: ReturnType<typeof setInterval> | null = null;
|
let zamanlayici: ReturnType<typeof setInterval> | null = null;
|
||||||
let denemeSayisi = 0;
|
let denemeSayisi = 0;
|
||||||
let kuyrukKapali = false;
|
let kuyrukKapali = false;
|
||||||
@@ -83,11 +87,21 @@ function zamanlayiciyiDurdur(): void {
|
|||||||
zamanlayici = null;
|
zamanlayici = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Bekleyen olayları geliş sırasıyla gönderir. */
|
/** Önce bekleyen kimliği uygular, sonra olayları geliş sırasıyla gönderir
|
||||||
|
* (kuyruktaki olaylar anonim profile değil tanımlı kullanıcıya yazılsın). */
|
||||||
function kuyruguBosalt(rybbit: RybbitApi): void {
|
function kuyruguBosalt(rybbit: RybbitApi): void {
|
||||||
const bekleyenler = kuyruk;
|
const bekleyenler = kuyruk;
|
||||||
|
const kimlik = bekleyenKimlik;
|
||||||
kuyruk = [];
|
kuyruk = [];
|
||||||
|
bekleyenKimlik = null;
|
||||||
zamanlayiciyiDurdur();
|
zamanlayiciyiDurdur();
|
||||||
|
if (kimlik) {
|
||||||
|
try {
|
||||||
|
rybbit.identify(kimlik[0], kimlik[1]);
|
||||||
|
} catch {
|
||||||
|
// yut
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const [ad, ozellikler] of bekleyenler) {
|
for (const [ad, ozellikler] of bekleyenler) {
|
||||||
try {
|
try {
|
||||||
rybbit.event(ad, ozellikler);
|
rybbit.event(ad, ozellikler);
|
||||||
@@ -97,23 +111,29 @@ function kuyruguBosalt(rybbit: RybbitApi): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function kuyrugaEkle(ad: OlayAdi, ozellikler?: Ozellikler): void {
|
/** Script'i bekleyen yoklamayı başlatır (olay kuyruğu ve kimlik slotu ortak). */
|
||||||
if (kuyrukKapali || kuyruk.length >= KUYRUK_SINIRI) return;
|
function zamanlayiciyiBaslat(): void {
|
||||||
kuyruk.push([ad, ozellikler]);
|
|
||||||
if (zamanlayici !== null) return;
|
if (zamanlayici !== null) return;
|
||||||
zamanlayici = setInterval(() => {
|
zamanlayici = setInterval(() => {
|
||||||
denemeSayisi += 1;
|
denemeSayisi += 1;
|
||||||
if (window.rybbit) {
|
if (window.rybbit) {
|
||||||
kuyruguBosalt(window.rybbit);
|
kuyruguBosalt(window.rybbit);
|
||||||
} else if (denemeSayisi >= DENEME_SINIRI) {
|
} else if (denemeSayisi >= DENEME_SINIRI) {
|
||||||
// Script gelmedi: bekleyenleri at, sonraki olaylar eski no-op'a dönsün
|
// Script gelmedi: bekleyenleri at, sonraki çağrılar eski no-op'a dönsün
|
||||||
kuyruk = [];
|
kuyruk = [];
|
||||||
|
bekleyenKimlik = null;
|
||||||
kuyrukKapali = true;
|
kuyrukKapali = true;
|
||||||
zamanlayiciyiDurdur();
|
zamanlayiciyiDurdur();
|
||||||
}
|
}
|
||||||
}, DENEME_ARALIGI_MS);
|
}, DENEME_ARALIGI_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function kuyrugaEkle(ad: OlayAdi, ozellikler?: Ozellikler): void {
|
||||||
|
if (kuyrukKapali || kuyruk.length >= KUYRUK_SINIRI) return;
|
||||||
|
kuyruk.push([ad, ozellikler]);
|
||||||
|
zamanlayiciyiBaslat();
|
||||||
|
}
|
||||||
|
|
||||||
/** Özel olay gönderir. Script henüz yoksa kısa süre kuyrukta bekletir. */
|
/** Özel olay gönderir. Script henüz yoksa kısa süre kuyrukta bekletir. */
|
||||||
export function olay(ad: OlayAdi, ozellikler?: Ozellikler): void {
|
export function olay(ad: OlayAdi, ozellikler?: Ozellikler): void {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
@@ -122,8 +142,8 @@ export function olay(ad: OlayAdi, ozellikler?: Ozellikler): void {
|
|||||||
kuyrugaEkle(ad, ozellikler);
|
kuyrugaEkle(ad, ozellikler);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Sıra bozulmasın: bekleyen varsa önce onlar gider
|
// Sıra bozulmasın: bekleyen (kimlik ya da olay) varsa önce onlar gider
|
||||||
if (kuyruk.length > 0) kuyruguBosalt(window.rybbit);
|
if (kuyruk.length > 0 || bekleyenKimlik) kuyruguBosalt(window.rybbit);
|
||||||
window.rybbit.event(ad, ozellikler);
|
window.rybbit.event(ad, ozellikler);
|
||||||
} catch {
|
} catch {
|
||||||
// Analitik hiçbir koşulda kullanıcı akışını bozmaz
|
// Analitik hiçbir koşulda kullanıcı akışını bozmaz
|
||||||
@@ -174,6 +194,8 @@ export function siraKovasi(sira: number): string {
|
|||||||
* Giriş yapan kullanıcıyı eşler. İlk çağrıda o cihazdaki önceki anonim
|
* Giriş yapan kullanıcıyı eşler. İlk çağrıda o cihazdaki önceki anonim
|
||||||
* olaylar geriye dönük olarak bu kullanıcıya bağlanır (sihirbazı doldurup
|
* olaylar geriye dönük olarak bu kullanıcıya bağlanır (sihirbazı doldurup
|
||||||
* sonra giriş yapan öğrencinin yolculuğu tek profilde birleşsin diye).
|
* sonra giriş yapan öğrencinin yolculuğu tek profilde birleşsin diye).
|
||||||
|
* Script henüz yoksa kimlik tek slotta bekler; kuyruk boşaltılırken
|
||||||
|
* olaylardan ÖNCE uygulanır.
|
||||||
*/
|
*/
|
||||||
export function kullaniciTanit(
|
export function kullaniciTanit(
|
||||||
kullaniciId: string,
|
kullaniciId: string,
|
||||||
@@ -181,15 +203,25 @@ export function kullaniciTanit(
|
|||||||
): void {
|
): void {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
try {
|
try {
|
||||||
window.rybbit?.identify(kullaniciId, traits);
|
if (!window.rybbit) {
|
||||||
|
if (kuyrukKapali) return;
|
||||||
|
bekleyenKimlik = [kullaniciId, traits];
|
||||||
|
zamanlayiciyiBaslat();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Doğrudan uygulanır; kuyrukta olay bekliyorsa sonraki boşaltmada bu
|
||||||
|
// kimlikle gider. Eski slot değeri geçersiz kalmasın diye silinir.
|
||||||
|
bekleyenKimlik = null;
|
||||||
|
window.rybbit.identify(kullaniciId, traits);
|
||||||
} catch {
|
} catch {
|
||||||
// yut
|
// yut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Çıkışta kimliği temizler. */
|
/** Çıkışta kimliği temizler (bekleyen kimlik slotu dahil). */
|
||||||
export function kullaniciTemizle(): void {
|
export function kullaniciTemizle(): void {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
|
bekleyenKimlik = null;
|
||||||
try {
|
try {
|
||||||
window.rybbit?.clearUserId();
|
window.rybbit?.clearUserId();
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user