feat(landing): hero Ara → /demo for empty input or example VIN match

Real visitors were repeatedly clicking the hero "Ara" button while only the
placeholder VIN (WVWZZZ1JZ3W597935) was showing — they mistook the example
for typed text. The click hit handleVinSearch's `if (!trimmed) return`
early-out and did nothing, leaving them stuck.

Now: empty input OR a value that exactly matches the example VIN routes to
/demo (the pre-warmed VW Golf 2003 catalog) instead of /register. The button
label also updates to "Örnek aracı dene" in that state so the outcome is
predictable before the click. Any other typed VIN still goes through the
existing /register?vin= flow unchanged.

PostHog: emits hero_ara_demo_redirect with {had_value, was_example_match}
so we can split the funnel by what triggered the demo entry.
This commit is contained in:
2026-06-02 00:17:40 +03:00
parent 078076b619
commit 1608da9319

View File

@@ -31,6 +31,13 @@ import {
} from "lucide-react";
import { Suspense, lazy, useEffect, useRef, useState } from "react";
// The example VIN shown as the hero input placeholder. Clicking "Ara" with
// the input empty (or already containing this exact VIN — common when users
// mistake the placeholder for typed text) opens /demo with the pre-warmed
// VW Golf 2003 catalog instead of stalling at the signup wall. Any other
// VIN takes the normal /register?vin= path.
const EXAMPLE_VIN = "WVWZZZ1JZ3W597935";
// Remotion — lazy loaded to keep initial bundle lean
const RemotionSchemaPlayer = lazy(() =>
Promise.all([import("@remotion/player"), import("@/remotion/SchemaDemo")]).then(
@@ -366,8 +373,25 @@ export function HomePage() {
}, [vin]);
const handleVinSearch = async () => {
const trimmed = vin.trim();
if (!trimmed) return;
const trimmed = vin.trim().toUpperCase();
// Empty input OR the example VIN itself → open the public demo instead
// of the signup wall. Real visitors were repeatedly clicking "Ara" with
// the placeholder showing because they mistook it for typed text; this
// turns that dead-end click into an "aha" catalog browse.
if (!trimmed || trimmed === EXAMPLE_VIN) {
capture("hero_ara_demo_redirect", {
had_value: !!trimmed,
was_example_match: trimmed === EXAMPLE_VIN,
});
navigate({
to: "/demo",
search: {
source: trimmed === EXAMPLE_VIN ? "hero_example_match" : "hero_empty",
},
});
return;
}
// Read latest auth state directly from store (avoids stale closure)
const { user, isLoading } = useAuthStore.getState();
@@ -430,7 +454,7 @@ export function HomePage() {
};
const fillExampleVin = () => {
setVin("WVWZZZ1JZ3W597935");
setVin(EXAMPLE_VIN);
setIsExampleVin(true);
};
@@ -933,7 +957,13 @@ export function HomePage() {
</>
) : (
<>
{t("landing.hero.searchCta")}
{/* When the input is empty or already holds the example
VIN, the button takes the visitor to /demo instead of
the signup wall — surface that intent in the label so
the click outcome is predictable. */}
{vin.trim() === "" || vin.trim().toUpperCase() === EXAMPLE_VIN
? "Örnek aracı dene"
: t("landing.hero.searchCta")}
<ArrowRight className="ml-2 size-4" />
</>
)}