From 73c5167cbb3df88c3bbd6332b7b7c242306e6445 Mon Sep 17 00:00:00 2001 From: backryun Date: Wed, 12 Aug 2026 13:48:25 -0300 Subject: [PATCH] fix(dashboard): retarget Kimi promo CTA to the API platform aff link Moonshot cannot sell coding plan subscriptions to most new users, so the Get Kimi Code traffic could not convert. At their request the dashboard banner and the README promotional spots now point at platform.kimi.ai?aff=omniroute with partner-approved copy, in all 43 locales. The dismissal key bumps to -v2 so the retargeted banner shows once to users who dismissed the old one, and the in-app title finally adopts the founding Open Source Friend framing agreed in July (title key renamed to foundingFriendTitle per the value-drift gate rename rule). Kimi Code provider pages keep kimi.com/code on purpose: they serve existing coding plan subscribers. Also un-excludes the now-fixed kimiSponsorBanner.test.tsx from vitest.config.ts (#8618 is closed). --- README.md | 4 +-- .../dashboard/KimiSponsorBanner.tsx | 22 +++++++++------- src/i18n/messages/ar.json | 6 ++--- src/i18n/messages/az.json | 6 ++--- src/i18n/messages/bg.json | 6 ++--- src/i18n/messages/bn.json | 6 ++--- src/i18n/messages/cs.json | 6 ++--- src/i18n/messages/da.json | 6 ++--- src/i18n/messages/de.json | 6 ++--- src/i18n/messages/en.json | 6 ++--- src/i18n/messages/es.json | 6 ++--- src/i18n/messages/fa.json | 6 ++--- src/i18n/messages/fi.json | 6 ++--- src/i18n/messages/fr.json | 6 ++--- src/i18n/messages/gu.json | 6 ++--- src/i18n/messages/he.json | 6 ++--- src/i18n/messages/hi.json | 6 ++--- src/i18n/messages/hu.json | 6 ++--- src/i18n/messages/id.json | 6 ++--- src/i18n/messages/in.json | 6 ++--- src/i18n/messages/it.json | 6 ++--- src/i18n/messages/ja.json | 6 ++--- src/i18n/messages/ko.json | 6 ++--- src/i18n/messages/mr.json | 6 ++--- src/i18n/messages/ms.json | 6 ++--- src/i18n/messages/nl.json | 6 ++--- src/i18n/messages/no.json | 6 ++--- src/i18n/messages/phi.json | 6 ++--- src/i18n/messages/pl.json | 6 ++--- src/i18n/messages/pt-BR.json | 6 ++--- src/i18n/messages/pt.json | 6 ++--- src/i18n/messages/ro.json | 6 ++--- src/i18n/messages/ru.json | 6 ++--- src/i18n/messages/sk.json | 6 ++--- src/i18n/messages/sv.json | 6 ++--- src/i18n/messages/sw.json | 6 ++--- src/i18n/messages/ta.json | 6 ++--- src/i18n/messages/te.json | 6 ++--- src/i18n/messages/th.json | 6 ++--- src/i18n/messages/tr.json | 6 ++--- src/i18n/messages/uk-UA.json | 6 ++--- src/i18n/messages/ur.json | 6 ++--- src/i18n/messages/vi.json | 6 ++--- src/i18n/messages/zh-CN.json | 6 ++--- src/i18n/messages/zh-TW.json | 6 ++--- tests/unit/ui/kimiSponsorBanner.test.tsx | 25 +++++++++++++------ vitest.config.ts | 1 - 47 files changed, 161 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 9aa175ff4358..c870342d1228 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ curl http://localhost:20128/v1/chat/completions \

- + Kimi K3 — Open Frontier Intelligence · 2.8T parameters · 1M-token context

@@ -228,7 +228,7 @@ curl http://localhost:20128/v1/chat/completions \
- + Kimi (Moonshot AI) diff --git a/src/app/(dashboard)/dashboard/KimiSponsorBanner.tsx b/src/app/(dashboard)/dashboard/KimiSponsorBanner.tsx index 13ce4272455e..50291dc19951 100644 --- a/src/app/(dashboard)/dashboard/KimiSponsorBanner.tsx +++ b/src/app/(dashboard)/dashboard/KimiSponsorBanner.tsx @@ -7,14 +7,18 @@ import { APP_CONFIG } from "@/shared/constants/appConfig"; import { shouldShowKimiSponsorBanner } from "./kimiSponsorBannerGate"; // Official Kimi partnership tracking link — keep in sync with README.md's -// Sponsors section and the aff links wired in the providers onboarding UI -// (ProviderPageHeader.tsx). -const KIMI_CODING_AFF_URL = "https://www.kimi.com/code?aff=omniroute"; +// Open Source Friends section and the aff links wired in the providers +// onboarding UI (ProviderPageHeader.tsx). Retargeted 2026-08 from the coding +// plan (kimi.com/code) to the API platform at Moonshot's request: coding plan +// subscriptions are closed to most new users, so that traffic could not +// convert. +const KIMI_PLATFORM_AFF_URL = "https://platform.kimi.ai?aff=omniroute"; -// Versioned dismissal key — bump the suffix (e.g. `-v2`) if the banner's +// Versioned dismissal key — bump the suffix (e.g. `-v3`) if the banner's // offer/copy ever changes materially enough to warrant re-showing it to -// users who already dismissed the previous version. -const DISMISS_STORAGE_KEY = "omniroute-kimi-sponsor-banner-dismissed-v1"; +// users who already dismissed the previous version. `-v2` = the 2026-08 CTA +// retarget to the API platform (new destination + new copy). +const DISMISS_STORAGE_KEY = "omniroute-kimi-sponsor-banner-dismissed-v2"; // Same-tab signal for the dismiss button, since writing localStorage doesn't // fire a "storage" event in the tab that wrote it. const DISMISS_EVENT = "omniroute:kimi-sponsor-banner-dismissed"; @@ -69,7 +73,7 @@ export default function KimiSponsorBanner() { return (
@@ -77,7 +81,7 @@ export default function KimiSponsorBanner() {
-

{t("title")}

+

{t("foundingFriendTitle")}

{t("description")}

@@ -85,7 +89,7 @@ export default function KimiSponsorBanner() {
({ useTranslations: () => (k: string) => k })); vi.mock("@/shared/components/ProviderIcon", () => ({ default: () => null })); @@ -21,9 +22,8 @@ async function renderBanner(version: string): Promise { vi.doMock("@/shared/constants/appConfig", () => ({ APP_CONFIG: { name: "OmniRoute", description: "AI Gateway", version }, })); - const { default: KimiSponsorBanner } = await import( - "../../../src/app/(dashboard)/dashboard/KimiSponsorBanner" - ); + const { default: KimiSponsorBanner } = + await import("../../../src/app/(dashboard)/dashboard/KimiSponsorBanner"); const container = document.createElement("div"); document.body.appendChild(container); @@ -48,13 +48,13 @@ describe("KimiSponsorBanner", () => { vi.doUnmock("@/shared/constants/appConfig"); }); - it("renders with the CTA pointing at the Kimi Coding aff link inside the version window", async () => { + it("renders with the CTA pointing at the Kimi API Platform aff link inside the version window", async () => { const container = await renderBanner("3.8.49"); - expect(container.textContent).toContain("title"); + expect(container.textContent).toContain("foundingFriendTitle"); expect(container.textContent).toContain("cta"); const link = container.querySelector("a[href]"); expect(link).not.toBeNull(); - expect(link?.getAttribute("href")).toBe(KIMI_CODING_AFF_URL); + expect(link?.getAttribute("href")).toBe(KIMI_PLATFORM_AFF_URL); expect(link?.getAttribute("target")).toBe("_blank"); expect(link?.getAttribute("rel")).toContain("noopener"); }); @@ -98,4 +98,13 @@ describe("KimiSponsorBanner", () => { const container = await renderBanner("3.8.49"); expect(container.querySelector("[role='complementary']")).toBeNull(); }); + + it("re-shows the retargeted banner to users who dismissed the v1 (Get Kimi Code) version", async () => { + // 2026-08 CTA retarget (coding plan -> API platform) bumped the dismissal + // key to -v2 so the whole install base gets one fresh impression. + localStorage.setItem(LEGACY_V1_STORAGE_KEY, "true"); + const container = await renderBanner("3.8.50"); + expect(container.querySelector("[role='complementary']")).not.toBeNull(); + localStorage.removeItem(LEGACY_V1_STORAGE_KEY); + }); }); diff --git a/vitest.config.ts b/vitest.config.ts index d602eecb71ef..49856274a5b0 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -40,7 +40,6 @@ export default defineConfig({ "tests/e2e/protocol-clients.test.ts", // ── Pre-existing failures tracked by #8618 ─────────────────────────────── "open-sse/services/autoCombo/__tests__/providerDiversity.test.ts", // #8618 — pre-existing failure; remove this exclusion when fixed - "tests/unit/ui/kimiSponsorBanner.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed "tests/unit/ui/compareView.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed "tests/unit/ui/model-select-modal-keep-open.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed "tests/unit/ui/model-select-field-6540.test.tsx", // #8618 — pre-existing failure; remove this exclusion when fixed