feat(FN-282): add social proof impression tracking to testimonial and trust components
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled

Commits merged:
- feat(FN-282): add social proof impression tracking to testimonial and trust components

Files changed:
apps/web/src/routes/_auth.tsx                      | 42 +++++++++++-
 .../src/routes/dashboard/subscription/index.tsx    | 80 ++++++++++++++++++++--
 2 files changed, 117 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-282
This commit is contained in:
Fusion
2026-05-13 06:36:05 +00:00
parent d855b564bf
commit c0fef5921b
2 changed files with 117 additions and 5 deletions

View File

@@ -1,11 +1,38 @@
import { capture } from "@/lib/posthog";
import { Link, Outlet, createFileRoute } from "@tanstack/react-router";
import { Database, ShieldCheck, Zap } from "lucide-react";
import { useEffect, useRef } from "react";
export const Route = createFileRoute("/_auth")({
component: AuthLayout,
});
function AuthLayout() {
const testimonialRef = useRef<HTMLDivElement>(null);
const impressionFiredRef = useRef(false);
// Social proof impression tracking
useEffect(() => {
const el = testimonialRef.current;
if (!el) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !impressionFiredRef.current) {
impressionFiredRef.current = true;
capture("social_proof_impression", { page: "auth" });
}
},
{ threshold: 0.5 },
);
observer.observe(el);
return () => observer.disconnect();
}, []);
function handleTestimonialClick() {
capture("social_proof_engaged", { page: "auth" });
}
return (
<div className="flex min-h-screen">
{/* Left Panel — Form */}
@@ -101,7 +128,20 @@ function AuthLayout() {
</p>
{/* Testimonial */}
<div className="rounded-2xl border border-border bg-surface/40 p-6 backdrop-blur-sm">
<div
ref={testimonialRef}
// biome-ignore lint/a11y/useSemanticElements: analytics-only interaction on content block
role="button"
tabIndex={0}
onClick={handleTestimonialClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handleTestimonialClick();
}
}}
className="rounded-2xl border border-border bg-surface/40 p-6 backdrop-blur-sm cursor-pointer"
>
<p className="text-sm leading-relaxed text-foreground/85">
&ldquo;Sase.tr&apos;ye geçtiğimizden beri yanlış parça siparişlerimiz neredeyse sıfıra
indi. Aylık 40 saatin üzerinde zaman tasarrufu sağlıyoruz.&rdquo;

View File

@@ -392,6 +392,54 @@ export function SubscriptionPage() {
return () => observer.disconnect();
}, [selectedPlanKey]);
// ─── Social proof impression tracking ────────────────────────────────────
const trustBadgesRef = useRef<HTMLDivElement>(null);
const paymentTrustRef = useRef<HTMLDivElement>(null);
const trustImpressionFiredRef = useRef(false);
const paymentTrustImpressionFiredRef = useRef(false);
useEffect(() => {
const el = trustBadgesRef.current;
if (!el) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !trustImpressionFiredRef.current) {
trustImpressionFiredRef.current = true;
capture("social_proof_impression", { page: "subscription", section: "trust_badges" });
}
},
{ threshold: 0.5 },
);
observer.observe(el);
return () => observer.disconnect();
}, []);
useEffect(() => {
const el = paymentTrustRef.current;
if (!el) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && !paymentTrustImpressionFiredRef.current) {
paymentTrustImpressionFiredRef.current = true;
capture("social_proof_impression", { page: "subscription", section: "payment_trust" });
}
},
{ threshold: 0.5 },
);
observer.observe(el);
return () => observer.disconnect();
}, []);
function handleTrustBadgesClick() {
capture("social_proof_engaged", { page: "subscription", section: "trust_badges" });
}
function handlePaymentTrustClick() {
capture("social_proof_engaged", { page: "subscription", section: "payment_trust" });
}
// ─── Loading state ─────────────────────────────────────────────────────────
if (isLoading) {
return (
@@ -826,7 +874,20 @@ export function SubscriptionPage() {
<ShieldCheck className="mr-2 h-4 w-4" />
{trialMutation.isPending ? t("common.loading") : t("subscription.startTrial")}
</Button>
<div className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1 text-xs leading-5 text-foreground/70">
<div
ref={trustBadgesRef}
// biome-ignore lint/a11y/useSemanticElements: analytics-only interaction on content block
role="button"
tabIndex={0}
onClick={handleTrustBadgesClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handleTrustBadgesClick();
}
}}
className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1 text-xs leading-5 text-foreground/70 cursor-pointer"
>
<span className="flex items-center gap-1">
<CreditCard className="h-3 w-3 shrink-0" />
{t("subscription.trustNoCard")}
@@ -1072,9 +1133,20 @@ export function SubscriptionPage() {
})()}
</Button>
</div>
<section
<div
ref={paymentTrustRef}
// biome-ignore lint/a11y/useSemanticElements: analytics-only interaction on content block
role="button"
tabIndex={0}
onClick={handlePaymentTrustClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handlePaymentTrustClick();
}
}}
aria-label="Ödeme güvencesi"
className="flex flex-wrap items-center justify-end gap-x-3 gap-y-1 text-xs leading-5 text-foreground/70"
className="flex flex-wrap items-center justify-end gap-x-3 gap-y-1 text-xs leading-5 text-foreground/70 cursor-pointer"
>
<span aria-hidden="true">🔒</span>
<span>{t("subscription.paymentTrustSSL")}</span>
@@ -1118,7 +1190,7 @@ export function SubscriptionPage() {
AmEx
</Badge>
</span>
</section>
</div>
</div>
</div>
</>