Integrate Rybbit analytics and enhance user tracking features
All checks were successful
Deploy / deploy (push) Successful in 16m7s

- Added Rybbit analytics configuration in .mcp.json for improved data collection.
- Updated layout.tsx to conditionally load the Rybbit analytics script in production.
- Enhanced user interaction tracking in various components, including GirisForm, RevizyonKutusu, and SatinAlForm, by logging specific events.
- Updated privacy policy page to reflect new data handling practices and added a section on service providers and data transfer.
- Improved user navigation and experience by integrating Rybbit's live visitor widget in the site footer.
This commit is contained in:
bilalgursen
2026-08-02 19:29:42 +03:00
parent cc9686147e
commit 0b92f999bc
22 changed files with 499 additions and 16 deletions

166
src/lib/eposta.ts Normal file
View File

@@ -0,0 +1,166 @@
/**
* E-posta şablonları.
*
* Kurallar: mail istemcileri harici CSS, <style> kuralı, flexbox ve SVG
* desteğini güvenilir biçimde sunmaz — bu yüzden düzen tablo tabanlı ve tüm
* stiller satır içi. Logo işareti de SVG yerine renkli hücrelerle yeniden
* çizilir (Outlook masaüstü border-radius'u yok sayar; kareler köşeli görünür,
* kabul edilebilir bozulma).
*/
const MAVI = "#3b82f6";
const SEFTALI = "#fdc7a7";
const TURUNCU = "#ff5a00";
const LACIVERT = "#0f172b";
const GRI = "#475569";
const KENAR = "#e2e8f0";
const ZEMIN = "#f8fafc";
const YAZI_TIPI =
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
export type EpostaIcerik = {
subject: string;
html: string;
text: string;
};
/** HTML bağlamına gömülen değerleri kaçırır — token'lı URL'lerdeki & şart. */
function kacir(deger: string): string {
return deger
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
/** Logo işareti: üç yuvarlak kare + KolayTercih kelime markası. */
function baslik(): string {
return `
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding-right:8px;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="19" height="19" style="width:19px;height:19px;background-color:${MAVI};border-radius:5px;font-size:0;line-height:0;">&nbsp;</td>
<td width="4" style="width:4px;font-size:0;line-height:0;">&nbsp;</td>
<td>
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="18" height="18" style="width:18px;height:18px;background-color:${SEFTALI};border-radius:5px;font-size:0;line-height:0;">&nbsp;</td>
</tr>
<tr>
<td height="4" style="height:4px;font-size:0;line-height:0;">&nbsp;</td>
</tr>
<tr>
<td width="18" height="18" style="width:18px;height:18px;background-color:${TURUNCU};border-radius:5px;font-size:0;line-height:0;">&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td style="font-family:${YAZI_TIPI};font-size:20px;letter-spacing:-0.5px;color:${LACIVERT};">
<span style="font-weight:300;">Kolay</span><span style="font-weight:600;">Tercih</span>
</td>
</tr>
</table>`;
}
/**
* Tüm e-postaların ortak kabuğu: dış zemin, beyaz kart, logo ve alt bilgi.
* `onizleme` gelen kutusunda konunun yanında görünen gizli özet metindir.
*/
function kabuk({
onizleme,
govde,
}: {
onizleme: string;
govde: string;
}): string {
return `<!doctype html>
<html lang="tr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="light">
<title>KolayTercih</title>
</head>
<body style="margin:0;padding:0;background-color:${ZEMIN};">
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;font-size:1px;line-height:1px;">${onizleme}</div>
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color:${ZEMIN};">
<tr>
<td align="center" style="padding:32px 16px;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:520px;">
<tr>
<td style="padding-bottom:20px;">${baslik()}</td>
</tr>
<tr>
<td style="background-color:#ffffff;border:1px solid ${KENAR};border-radius:16px;padding:32px;font-family:${YAZI_TIPI};font-size:15px;line-height:1.65;color:${GRI};">
${govde}
</td>
</tr>
<tr>
<td style="padding:20px 8px 0;font-family:${YAZI_TIPI};font-size:12px;line-height:1.6;color:#94a3b8;">
KolayTercih &middot; YKS tercih listeni dakikalar içinde hazırla<br>
Bu e-postayı hesabınla ilgili bir işlem yaptığın için aldın.
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>`;
}
/** Ortalanmış, tablo tabanlı CTA butonu (Outlook'ta da zemin rengi tutar). */
function buton(url: string, etiket: string): string {
return `
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" style="background-color:${MAVI};border-radius:10px;">
<a href="${url}" style="display:inline-block;padding:14px 28px;font-family:${YAZI_TIPI};font-size:15px;font-weight:600;color:#ffffff;text-decoration:none;">${etiket} &rarr;</a>
</td>
</tr>
</table>`;
}
export function magicLinkEpostasi(url: string): EpostaIcerik {
const guvenliUrl = kacir(url);
const govde = `
<h1 style="margin:0 0 12px;font-family:${YAZI_TIPI};font-size:22px;line-height:1.35;font-weight:700;color:${LACIVERT};">
Giriş bağlantın hazır
</h1>
<p style="margin:0 0 24px;">
Aşağıdaki butona tıklayarak KolayTercih hesabına giriş yapabilirsin.
Bağlantı <strong style="color:${LACIVERT};">5 dakika</strong> geçerli ve
yalnızca bir kez kullanılabilir.
</p>
${buton(guvenliUrl, "Giriş yap")}
<p style="margin:24px 0 0;font-size:13px;">
Buton çalışmazsa bu adresi tarayıcının adres çubuğuna yapıştır:<br>
<a href="${guvenliUrl}" style="color:${MAVI};word-break:break-all;">${guvenliUrl}</a>
</p>
<div style="margin:24px 0 0;padding-top:20px;border-top:1px solid ${KENAR};font-size:13px;color:#94a3b8;">
Bu isteği sen yapmadıysan bu e-postayı yok sayabilirsin; bağlantıya
tıklanmadığı sürece hesabında hiçbir şey değişmez.
</div>`;
return {
subject: "KolayTercih giriş bağlantın",
html: kabuk({
onizleme: "Giriş bağlantın 5 dakika geçerli.",
govde,
}),
text: [
"KolayTercih giriş bağlantın",
"",
"Hesabına giriş yapmak için bu adresi tarayıcında aç:",
url,
"",
"Bağlantı 5 dakika geçerli ve yalnızca bir kez kullanılabilir.",
"Bu isteği sen yapmadıysan bu e-postayı yok sayabilirsin.",
].join("\n"),
};
}