fix(analytics): connect directly to Rybbit to preserve real visitor IP
Some checks failed
Build and Deploy / build (push) Has been cancelled

Changed Rybbit script loading from server-side rewrite to client-side direct
connection. This prevents Next.js from proxying the request, which was causing
all visitor IPs to show as the Hetzner server IP (138.201.11.251).

Before:
- Browser → Next.js → Rybbit (server-side proxy, loses client IP)

After:
- Browser → Rybbit (direct connection, real IP preserved)

Changes:
- layout.tsx: Use direct Rybbit URL for script src
- next.config.ts: Remove /api/script.js rewrite
This commit is contained in:
Unchained
2026-04-03 20:10:59 +02:00
parent 0f00aa8a47
commit d999d739d5
2 changed files with 19 additions and 7 deletions

View File

@@ -34,10 +34,8 @@ const nextConfig: NextConfig = {
async rewrites() {
const rybbitHost = process.env.NEXT_PUBLIC_RYBBIT_HOST || "https://rybbit.nodecrew.me";
return [
{
source: "/api/script.js",
destination: `${rybbitHost}/api/script.js`,
},
// Note: /api/script.js now connects directly to Rybbit (client-side)
// to preserve real visitor IP instead of proxying through Next.js
{
source: "/api/track",
destination: "/api/rybbit/track",

View File

@@ -3,9 +3,10 @@ import { NextIntlClientProvider } from "next-intl";
import { getMessages, setRequestLocale } from "next-intl/server";
import { SUPPORTED_LOCALES, DEFAULT_LOCALE, isValidLocale } from "@/lib/i18n/locales";
import Script from "next/script";
import AnalyticsProvider from "@/components/providers/AnalyticsProvider";
import ExitIntentDetector from "@/components/home/ExitIntentDetector";
const RYBBIT_SITE_ID = process.env.NEXT_PUBLIC_RYBBIT_SITE_ID || "1";
const RYBBIT_HOST = process.env.NEXT_PUBLIC_RYBBIT_HOST || "https://rybbit.nodecrew.me";
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://manoonoils.com";
@@ -49,14 +50,27 @@ export default async function LocaleLayout({
return (
<>
<AnalyticsProvider clientId={process.env.NEXT_PUBLIC_OPENPANEL_CLIENT_ID || ""} />
<Script
src="/api/script.js"
src={`${RYBBIT_HOST}/api/script.js`}
data-site-id={RYBBIT_SITE_ID}
strategy="afterInteractive"
/>
<Script
id="mautic-tracking"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
(function(w,d,t,u,n,a,m){w['MauticTrackingObject']=n;
w[n]=w[n]||function(){(w[n].q=w[n].q||[]).push(arguments)},a=d.createElement(t),
m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://mautic.nodecrew.me/mtc.js','mt');
mt('send', 'pageview');
`,
}}
/>
<NextIntlClientProvider messages={messages}>
{children}
<ExitIntentDetector />
</NextIntlClientProvider>
</>
);