From dbd2eed8bc3daad16e894d240f9e5ee0fc4224a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?=
Date: Thu, 23 Apr 2026 00:22:56 +0300
Subject: [PATCH] Remove Ezoic ad integration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.env.example | 4 +-
src/app/ads.txt/route.ts | 17 ----
src/app/globals.css | 70 ----------------
src/app/layout.tsx | 3 -
src/app/privacy/page.tsx | 21 -----
src/app/prompts/[id]/page.tsx | 4 -
src/components/ads/ezoic-ad.tsx | 18 ----
src/components/ads/ezoic-placeholder.tsx | 43 ----------
src/components/layout/ezoic-ads.tsx | 88 --------------------
src/components/prompts/discovery-prompts.tsx | 19 -----
src/lib/ezoic.ts | 13 ---
src/lib/plugins/widgets/ezoic.tsx | 32 -------
src/lib/plugins/widgets/index.ts | 2 -
13 files changed, 1 insertion(+), 333 deletions(-)
delete mode 100644 src/app/ads.txt/route.ts
delete mode 100644 src/components/ads/ezoic-ad.tsx
delete mode 100644 src/components/ads/ezoic-placeholder.tsx
delete mode 100644 src/components/layout/ezoic-ads.tsx
delete mode 100644 src/lib/ezoic.ts
delete mode 100644 src/lib/plugins/widgets/ezoic.tsx
diff --git a/.env.example b/.env.example
index 12b19732..59507624 100644
--- a/.env.example
+++ b/.env.example
@@ -65,6 +65,4 @@ CRON_SECRET="your-secret-key-here"
# SENTRY_AUTH_TOKEN=sentry-auth-token
-# GOOGLE_ADSENSE_ACCOUNT=ca-pub-xxxxxxxxxxxxxxxx
-# NEXT_PUBLIC_EZOIC_ENABLED=true
-# EZOIC_SITE_DOMAIN=prompts.chat
\ No newline at end of file
+# GOOGLE_ADSENSE_ACCOUNT=ca-pub-xxxxxxxxxxxxxxxx
\ No newline at end of file
diff --git a/src/app/ads.txt/route.ts b/src/app/ads.txt/route.ts
deleted file mode 100644
index 19be5fe5..00000000
--- a/src/app/ads.txt/route.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { NextResponse } from "next/server";
-
-export async function GET() {
- const domain = process.env.EZOIC_SITE_DOMAIN;
-
- if (!domain) {
- return new NextResponse("# ads.txt not configured\n", {
- status: 200,
- headers: { "Content-Type": "text/plain" },
- });
- }
-
- return NextResponse.redirect(
- `https://srv.adstxtmanager.com/19390/${domain}`,
- 301
- );
-}
diff --git a/src/app/globals.css b/src/app/globals.css
index d2fe9c40..c1007341 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -802,73 +802,3 @@
padding: 0;
}
-/* Ezoic privacy policy container styling */
-#ezoic-privacy-policy-container {
- margin-top: 1rem;
- color: var(--muted-foreground);
-}
-
-#ezoic-privacy-policy-container h2,
-#ezoic-privacy-policy-container h3,
-#ezoic-privacy-policy-container h4 {
- font-size: 1rem;
- font-weight: 600;
- margin-top: 1rem;
- margin-bottom: 0.5rem;
- color: var(--foreground);
-}
-
-#ezoic-privacy-policy-container p {
- margin-top: 0.75rem;
- margin-bottom: 0.75rem;
- line-height: 1.7;
- color: var(--muted-foreground);
-}
-
-#ezoic-privacy-policy-container a {
- color: var(--primary);
- text-decoration: underline;
- text-underline-offset: 2px;
-}
-
-#ezoic-privacy-policy-container a:hover {
- opacity: 0.8;
-}
-
-#ezoic-privacy-policy-container ul,
-#ezoic-privacy-policy-container ol {
- margin-top: 0.75rem;
- margin-bottom: 0.75rem;
- padding-left: 1.5rem;
- color: var(--muted-foreground);
-}
-
-#ezoic-privacy-policy-container li {
- margin-top: 0.25rem;
- margin-bottom: 0.25rem;
-}
-
-#ezoic-privacy-policy-container table {
- width: 100%;
- border-collapse: collapse;
- margin: 1rem 0;
- font-size: 0.875rem;
-}
-
-#ezoic-privacy-policy-container th,
-#ezoic-privacy-policy-container td {
- border: 1px solid var(--border);
- padding: 0.5rem 0.75rem;
- text-align: left;
-}
-
-#ezoic-privacy-policy-container th {
- background: var(--muted);
- font-weight: 600;
-}
-
-/* Ezoic ad content: center and constrain injected ad creatives */
-.ezoic-ad-content * {
- margin-left: auto !important;
- margin-right: auto !important;
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 84d2ce81..997ef61e 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -7,7 +7,6 @@ import { Header } from "@/components/layout/header";
import { Footer } from "@/components/layout/footer";
import { CookieConsentBanner } from "@/components/layout/cookie-consent";
import { Analytics } from "@/components/layout/analytics";
-import { EzoicScripts, EzoicRouteHandler } from "@/components/layout/ezoic-ads";
import { WebsiteStructuredData } from "@/components/seo/structured-data";
import { AppBanner } from "@/components/layout/app-banner";
import { LocaleDetector } from "@/components/providers/locale-detector";
@@ -185,13 +184,11 @@ export default async function RootLayout({
)}
- {process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && }
{process.env.GOOGLE_ANALYTICS_ID && (
)}
- {process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && }
{isEmbedRoute || isKidsRoute ? (
children
diff --git a/src/app/privacy/page.tsx b/src/app/privacy/page.tsx
index 86e3efbd..1f0d1b5a 100644
--- a/src/app/privacy/page.tsx
+++ b/src/app/privacy/page.tsx
@@ -97,27 +97,6 @@ export default function PrivacyPage() {
- {process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && (
-
- Advertising & Ezoic
-
- We use Ezoic to provide personalized ads and analytics on this site. Ezoic and its partners
- may collect and use data about your visit to this and other websites to provide relevant
- advertisements. For full details on how Ezoic and its partners use your information, including
- a list of known cookies used on this site, please see the{" "}
-
- Ezoic privacy disclosures
- .
-
-
-
- )}
-
Your Rights & CC0 License
diff --git a/src/app/prompts/[id]/page.tsx b/src/app/prompts/[id]/page.tsx
index e86d593b..a03f33cf 100644
--- a/src/app/prompts/[id]/page.tsx
+++ b/src/app/prompts/[id]/page.tsx
@@ -33,7 +33,6 @@ import { AddToCollectionButton } from "@/components/prompts/add-to-collection-bu
import { getConfig } from "@/lib/config";
import { StructuredData } from "@/components/seo/structured-data";
import { AI_MODELS } from "@/lib/works-best-with";
-import { EzoicAd } from "@/components/ads/ezoic-ad";
interface PromptPageProps {
params: Promise<{ id: string }>;
@@ -710,9 +709,6 @@ export default async function PromptPage({ params }: PromptPageProps) {
locale={locale}
/>
)}
-
- {/* Ad Placement */}
- {process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && }
diff --git a/src/components/ads/ezoic-ad.tsx b/src/components/ads/ezoic-ad.tsx
deleted file mode 100644
index adadf963..00000000
--- a/src/components/ads/ezoic-ad.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-"use client";
-
-import { EzoicPlaceholder } from "./ezoic-placeholder";
-
-interface EzoicAdProps {
- id: number;
-}
-
-/**
- * Client-only wrapper for EzoicPlaceholder.
- * Renders the placeholder div after mount so it's in the DOM
- * when Ezoic's showAds() runs.
- *
- * @see https://docs.ezoic.com/docs/ezoicadsadvanced/nextjs/
- */
-export function EzoicAd({ id }: EzoicAdProps) {
- return ;
-}
diff --git a/src/components/ads/ezoic-placeholder.tsx b/src/components/ads/ezoic-placeholder.tsx
deleted file mode 100644
index bf124f92..00000000
--- a/src/components/ads/ezoic-placeholder.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import { useTranslations } from "next-intl";
-import { runEzoic } from "@/lib/ezoic";
-
-interface EzoicPlaceholderProps {
- id: number;
-}
-
-/**
- * Manages the lifecycle of a single Ezoic ad slot.
- * The placeholder div is always in the DOM so Ezoic can find it
- * when showAds() runs. Destroys the placeholder on unmount.
- *
- * @see https://docs.ezoic.com/docs/ezoicadsadvanced/nextjs/
- */
-export function EzoicPlaceholder({ id }: EzoicPlaceholderProps) {
- const t = useTranslations("common");
-
- useEffect(() => {
- runEzoic(() => {
- window.ezstandalone?.showAds(id);
- });
-
- return () => {
- runEzoic(() => {
- window.ezstandalone?.destroyPlaceholders(id);
- });
- };
- }, [id]);
-
- return (
-
- );
-}
diff --git a/src/components/layout/ezoic-ads.tsx b/src/components/layout/ezoic-ads.tsx
deleted file mode 100644
index cbbfbd89..00000000
--- a/src/components/layout/ezoic-ads.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-"use client";
-
-import { useEffect } from "react";
-import Script from "next/script";
-import { usePathname } from "next/navigation";
-import { runEzoic } from "@/lib/ezoic";
-
-declare global {
- interface Window {
- ezstandalone?: {
- cmd: Array<() => void>;
- showAds: (...ids: number[]) => void;
- destroyAll: () => void;
- destroyPlaceholders: (...ids: number[]) => void;
- [key: string]: unknown;
- };
- }
-}
-
-/**
- * Ezoic script loader — renders all required
-
- {/* Ezoic Analytics */}
-
- >
- );
-}
-
-/**
- * Handles SPA route changes for Ezoic.
- * Destroys stale placeholders and re-scans the DOM on each navigation.
- *
- * @see https://docs.ezoic.com/docs/ezoicadsadvanced/nextjs/
- */
-export function EzoicRouteHandler() {
- const pathname = usePathname();
-
- useEffect(() => {
- runEzoic(() => {
- window.ezstandalone?.destroyPlaceholders();
- requestAnimationFrame(() => {
- window.ezstandalone?.showAds();
- });
- });
- }, [pathname]);
-
- return null;
-}
-
diff --git a/src/components/prompts/discovery-prompts.tsx b/src/components/prompts/discovery-prompts.tsx
index e21e1da5..4a2fd80b 100644
--- a/src/components/prompts/discovery-prompts.tsx
+++ b/src/components/prompts/discovery-prompts.tsx
@@ -5,7 +5,6 @@ import { db } from "@/lib/db";
import { Button } from "@/components/ui/button";
import { Masonry } from "@/components/ui/masonry";
import { PromptCard } from "@/components/prompts/prompt-card";
-import { EzoicAd } from "@/components/ads/ezoic-ad";
interface DiscoveryPromptsProps {
isHomepage?: boolean;
@@ -158,15 +157,6 @@ export async function DiscoveryPrompts({ isHomepage = false }: DiscoveryPromptsP
)}
- {/* Ad Placement - after featured */}
- {isHomepage && process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && (
-
- )}
-
{/* Today's Most Upvoted Section */}
{todaysMostUpvoted.length > 0 && (
@@ -217,15 +207,6 @@ export async function DiscoveryPrompts({ isHomepage = false }: DiscoveryPromptsP
)}
- {/* Ad Placement - after latest */}
- {isHomepage && process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true" && (
-
- )}
-
{/* Recently Updated Section */}
{recentlyUpdated.length > 0 && (
diff --git a/src/lib/ezoic.ts b/src/lib/ezoic.ts
deleted file mode 100644
index 154b66d6..00000000
--- a/src/lib/ezoic.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Safely push a function to the Ezoic command queue.
- * Initializes window.ezstandalone and cmd array if they don't exist yet,
- * preventing errors when components mount before the Ezoic script loads.
- *
- * @see https://docs.ezoic.com/docs/ezoicadsadvanced/nextjs/
- */
-export function runEzoic(fn: () => void) {
- if (typeof window === "undefined") return;
- const ez = (window.ezstandalone ??= {} as NonNullable);
- ez.cmd = ez.cmd || [];
- ez.cmd.push(fn);
-}
diff --git a/src/lib/plugins/widgets/ezoic.tsx b/src/lib/plugins/widgets/ezoic.tsx
deleted file mode 100644
index b506e6e8..00000000
--- a/src/lib/plugins/widgets/ezoic.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { EzoicPlaceholder } from "@/components/ads/ezoic-placeholder";
-import type { WidgetPlugin } from "./types";
-
-// Placeholder IDs must match those created in the Ezoic dashboard.
-// Each repeated instance uses a unique ID (101, 102, 103, ...) to avoid
-// "unpredictable ad behaviour" per Ezoic infinite scroll docs.
-const EZOIC_FEED_BASE_ID = 101;
-
-export const ezoicWidget: WidgetPlugin = {
- id: "ezoic",
- name: "Ezoic Ads",
- prompts: [
- {
- id: "ezoic-feed-ad",
- slug: "ezoic-feed-ad",
- title: "",
- description: "",
- content: "",
- type: "TEXT",
- positioning: {
- position: 4,
- mode: "repeat",
- repeatEvery: 12,
- maxCount: 20,
- },
- shouldInject: () => process.env.NEXT_PUBLIC_EZOIC_ENABLED === "true",
- render: (instanceIndex: number) => (
-
- ),
- },
- ],
-};
diff --git a/src/lib/plugins/widgets/index.ts b/src/lib/plugins/widgets/index.ts
index cda40eda..ed25a9c3 100644
--- a/src/lib/plugins/widgets/index.ts
+++ b/src/lib/plugins/widgets/index.ts
@@ -3,7 +3,6 @@ import { coderabbitWidget } from "./coderabbit";
import { bookWidget } from "./book";
import { textreamWidget } from "./textream";
import { commandcodeWidget } from "./commandcode";
-import { ezoicWidget } from "./ezoic";
export * from "./types";
@@ -13,7 +12,6 @@ const widgetPlugins: WidgetPlugin[] = [
bookWidget,
textreamWidget,
commandcodeWidget,
- ezoicWidget,
];
/**