feat(analitik): giris_basarili sunucu olayı

Oturum oluşturulduğunda (databaseHooks.session.create.after) Rybbit'e
sunucudan giris_basarili düşer; yontem = eposta | google | diger
(better-auth uç yolundan türetilir). Huninin "link istendi → giriş yapıldı"
adımı bugüne dek ölçülemiyordu.

- await yok: Rybbit'in 3 sn'lik timeout'u girişi geciktirmez; sunucuOlayi
  hata fırlatmaz. E-posta adresi olaya girmez, yalnızca kullanıcı ID.
- RYBBIT_HOST/SITE_ID/API_KEY yoksa no-op — prod .env.production'da bu
  üçü bugün yok (bkz. ayrı ci.yaml commit'i), eklenene dek olay düşmez.

Giriş akışının davranışını değiştirmez (yalnızca yan etki ekler).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-21 04:52:27 +03:00
parent 2af4a9f781
commit 17046c830f
2 changed files with 25 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
import "server-only"; import "server-only";
/** /**
* Rybbit'e sunucudan olay gönderimi (POST /api/track). Yalnızca sunucu * Rybbit'e sunucudan olay gönderimi (POST /api/track). Yalnızca sunucu
* tarafından çağrılır (lib/odeme.ts) — anahtar NEXT_PUBLIC_ değil. * tarafından çağrılır (lib/odeme.ts, lib/auth.ts) — anahtar NEXT_PUBLIC_ değil.
* *
* Neden sunucu tarafı: ödeme dönüşümü tarayıcıdan gönderilirse reklam * Neden sunucu tarafı: ödeme dönüşümü tarayıcıdan gönderilirse reklam
* engelleyiciler ve iyzico dönüşünde kapatılan sekmeler yüzünden kaybolur. * engelleyiciler ve iyzico dönüşünde kapatılan sekmeler yüzünden kaybolur.
@@ -14,7 +14,7 @@ const HOST = process.env.RYBBIT_HOST;
const SITE_ID = process.env.RYBBIT_SITE_ID; const SITE_ID = process.env.RYBBIT_SITE_ID;
const API_KEY = process.env.RYBBIT_API_KEY; const API_KEY = process.env.RYBBIT_API_KEY;
export type SunucuOlayAdi = "odeme_tamamlandi"; export type SunucuOlayAdi = "odeme_tamamlandi" | "giris_basarili";
export async function sunucuOlayi( export async function sunucuOlayi(
ad: SunucuOlayAdi, ad: SunucuOlayAdi,

View File

@@ -2,6 +2,7 @@ import "server-only";
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { magicLink } from "better-auth/plugins"; import { magicLink } from "better-auth/plugins";
import { sunucuOlayi } from "./analitik-sunucu";
import { appDb, schema } from "./appdb"; import { appDb, schema } from "./appdb";
import { grantCredits, DENEME_KREDISI } from "./credits"; import { grantCredits, DENEME_KREDISI } from "./credits";
import { magicLinkEpostasi } from "./eposta"; import { magicLinkEpostasi } from "./eposta";
@@ -157,6 +158,28 @@ export const auth = betterAuth({
}, },
}, },
}, },
session: {
create: {
after: async (session, ctx) => {
// Huninin son adımı: oturum gerçekten açıldı. Sunucudan gider —
// reklam engelleyici ve kapanan sekme kaybettirmez. `await` YOK:
// Rybbit'in 3 sn'lik timeout'u girişi geciktirmesin (sunucuOlayi
// hata fırlatmaz). E-posta adresi özelliklere girmez.
const yol = ctx?.path ?? "";
void sunucuOlayi("giris_basarili", {
kullaniciId: session.userId,
pathname: "/giris",
ozellikler: {
yontem: yol.startsWith("/magic-link")
? "eposta"
: yol.startsWith("/callback")
? "google"
: "diger",
},
});
},
},
},
}, },
}); });