diff --git a/backend/src/settings/settings.service.ts b/backend/src/settings/settings.service.ts
index 48c5d4d..4bb0af4 100644
--- a/backend/src/settings/settings.service.ts
+++ b/backend/src/settings/settings.service.ts
@@ -571,6 +571,28 @@ export class SettingsService implements OnModuleInit {
if (obj.ogImageUrl) {
updates['ogImageUrl'] = String(obj.ogImageUrl);
}
+ if ('googleSiteVerification' in obj) {
+ updates['googleSiteVerification'] = String(obj.googleSiteVerification ?? '');
+ updates['google_site_verification'] = String(obj.googleSiteVerification ?? '');
+ }
+ if ('googleAnalyticsId' in obj) {
+ updates['googleAnalyticsId'] = String(obj.googleAnalyticsId ?? '');
+ updates['ga_measurement_id'] = String(obj.googleAnalyticsId ?? '');
+ }
+ if ('googleTagManagerId' in obj) {
+ updates['googleTagManagerId'] = String(obj.googleTagManagerId ?? '');
+ updates['gtm_id'] = String(obj.googleTagManagerId ?? '');
+ }
+ if ('enableGoogleAnalytics' in obj) {
+ updates['enableGoogleAnalytics'] = String(Boolean(obj.enableGoogleAnalytics));
+ }
+ if ('enableGoogleTagManager' in obj) {
+ updates['enableGoogleTagManager'] = String(Boolean(obj.enableGoogleTagManager));
+ }
+ if ('clarityProjectId' in obj) {
+ updates['clarityProjectId'] = String(obj.clarityProjectId ?? '');
+ updates['clarity_project_id'] = String(obj.clarityProjectId ?? '');
+ }
if (Object.keys(updates).length > 0) {
await this.updateBulkUiTexts(updates);
diff --git a/frontend/admin-panel/src/pages/SeoSettingsPage.tsx b/frontend/admin-panel/src/pages/SeoSettingsPage.tsx
index 1be3dc2..cf98671 100644
--- a/frontend/admin-panel/src/pages/SeoSettingsPage.tsx
+++ b/frontend/admin-panel/src/pages/SeoSettingsPage.tsx
@@ -1,5 +1,5 @@
import { useState, useEffect } from 'react';
-import { Globe, Save, Sliders, Monitor, Sparkles } from 'lucide-react';
+import { Globe, Save, Sliders, Monitor, Sparkles, Search, BarChart3, Code2, CheckCircle2, HelpCircle, Activity, ExternalLink, ShieldCheck } from 'lucide-react';
import { toast } from 'react-hot-toast';
import api from '../services/api';
import Spinner from '../components/ui/Spinner';
@@ -19,6 +19,12 @@ export default function SeoSettingsPage() {
keywords: 'مکمل سگ, مکمل گربه, داروی حیوانات, Canina Germany',
canonicalBaseUrl: 'https://canina.ir',
ogImageUrl: '/assets/images/regenerated_image_1779109861747.png',
+ googleSiteVerification: '',
+ googleAnalyticsId: '',
+ googleTagManagerId: '',
+ enableGoogleAnalytics: true,
+ enableGoogleTagManager: true,
+ clarityProjectId: '',
});
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
@@ -41,6 +47,12 @@ export default function SeoSettingsPage() {
keywords: data.keywords || prev.keywords,
canonicalBaseUrl: data.canonicalBaseUrl || prev.canonicalBaseUrl,
ogImageUrl: data.ogImageUrl || prev.ogImageUrl,
+ googleSiteVerification: data.googleSiteVerification || data.google_site_verification || '',
+ googleAnalyticsId: data.googleAnalyticsId || data.ga_measurement_id || '',
+ googleTagManagerId: data.googleTagManagerId || data.gtm_id || '',
+ enableGoogleAnalytics: data.enableGoogleAnalytics !== undefined ? Boolean(data.enableGoogleAnalytics) : true,
+ enableGoogleTagManager: data.enableGoogleTagManager !== undefined ? Boolean(data.enableGoogleTagManager) : true,
+ clarityProjectId: data.clarityProjectId || data.clarity_project_id || '',
}));
}
})
@@ -286,6 +298,279 @@ export default function SeoSettingsPage() {
+ {/* Section 3: Google Services & Webmaster Analytics */}
+
+
+
+
+
+ سرویسهای تحلیل و وبمستر گوگل (Google Services & Analytics)
+
+
+
+ اتصال آنی به فرانتاستور (Zero Build Delay) ⚡
+
+
+
+ {/* Grid of Webmaster Cards */}
+
+
+ {/* Google Search Console Card */}
+
+
+
+
+ GSC
+
+
+
+ گوگل سرچ کنسول (Google Search Console)
+
+
تأیید مالکیت دامنه در نتایج جستجوی گوگل
+
+
+ {seo.googleSiteVerification ? (
+
+
+ متصل
+
+ ) : (
+
+ تنظیم نشده
+
+ )}
+
+
+
+
+
{
+ let val = e.target.value.trim();
+ // Auto-extract content if user pasted full
+ const match = val.match(/content=["']([^"']+)["']/);
+ if (match && match[1]) {
+ val = match[1];
+ }
+ setSeo({ ...seo, googleSiteVerification: val });
+ }}
+ placeholder="مثال: abcdef1234567890 یا کل تگ
"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-blue-500 outline-none text-xs font-mono"
+ dir="ltr"
+ />
+
+ میتوانید کل تگ <meta name="google-site-verification"...> یا فقط مقدار داخل content را پیست کنید.
+
+
+
+ {seo.googleSiteVerification && (
+
+ متاتگ تزریق شده در سایت:
+
+ <meta name="google-site-verification" content="{seo.googleSiteVerification}" />
+
+
+ )}
+
+
+ {/* Google Analytics 4 (GA4) Card */}
+
+
+
+
+ GA4
+
+
+
+ گوگل آنالیتیکس ۴ (Google Analytics 4)
+
+
رهگیری بازدیدها، نرخ تبدیل و رفتار مشتریان
+
+
+
+
+
+
+
+
setSeo({ ...seo, googleAnalyticsId: e.target.value.trim() })}
+ placeholder="G-XXXXXXXXXX"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-amber-500 outline-none text-xs font-mono font-bold"
+ dir="ltr"
+ />
+
+ این شناسه با پیشوند G- از مسیر Admin > Data Streams در گوگل آنالیتیکس قابل دریافت است.
+
+
+
+
+ {seo.googleAnalyticsId && seo.enableGoogleAnalytics !== false ? (
+
+
+ اسکریپت gtag.js فعال و در حال رهگیری است
+
+ ) : (
+
+ {!seo.googleAnalyticsId ? 'شناسه GA4 هنوز ثبت نشده است.' : 'آمارگیر غیرفعال شده است.'}
+
+ )}
+
+
+
+ {/* Google Tag Manager (GTM) Card */}
+
+
+
+
+ GTM
+
+
+
+ گوگل تگ منیجر (Google Tag Manager)
+
+
مدیریت متمرکز تگها، ایونتها و تبلیغات گوگل ادز
+
+
+
+
+
+
+
+
setSeo({ ...seo, googleTagManagerId: e.target.value.trim() })}
+ placeholder="GTM-XXXXXXX"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-blue-500 outline-none text-xs font-mono font-bold"
+ dir="ltr"
+ />
+
+ شناسه با پیشوند GTM- در بالای داشبورد کانتینر تگ منیجر درج شده است.
+
+
+
+
+ {seo.googleTagManagerId && seo.enableGoogleTagManager !== false ? (
+
+
+ کانتینر GTM در Head و Noscript لود میشود
+
+ ) : (
+
+ {!seo.googleTagManagerId ? 'شناسه GTM ثبت نشده است.' : 'تگ منیجر غیرفعال شده است.'}
+
+ )}
+
+
+
+ {/* Microsoft Clarity Card */}
+
+
+
+
+ MS
+
+
+
+ مایکروسافت کلاریتی (Microsoft Clarity)
+
+
ضبط جلسات، نقشه حرارتی (Heatmap) و تحلیل کلیکها
+
+
+ {seo.clarityProjectId ? (
+
+
+ فعال
+
+ ) : (
+
+ اختیاری
+
+ )}
+
+
+
+
+
setSeo({ ...seo, clarityProjectId: e.target.value.trim() })}
+ placeholder="مثال: abcde12345"
+ className="w-full px-4 py-2.5 rounded-xl border border-gray-200 focus:border-orange-500 outline-none text-xs font-mono"
+ dir="ltr"
+ />
+
+ ابزار کاملاً رایگان مایکروسافت برای مشاهده رفتار خرید کاربران در صفحه محصول و چکاوت.
+
+
+
+
+
+
+
diff --git a/frontend/admin-panel/src/types/admin.ts b/frontend/admin-panel/src/types/admin.ts
index 3bf0fa0..fbf8f71 100644
--- a/frontend/admin-panel/src/types/admin.ts
+++ b/frontend/admin-panel/src/types/admin.ts
@@ -185,6 +185,12 @@ export interface SeoSettings {
keywords: string;
canonicalBaseUrl: string;
ogImageUrl: string;
+ googleSiteVerification?: string;
+ googleAnalyticsId?: string;
+ googleTagManagerId?: string;
+ enableGoogleAnalytics?: boolean;
+ enableGoogleTagManager?: boolean;
+ clarityProjectId?: string;
}
export interface FinancialSettings {
diff --git a/frontend/application/app/layout.tsx b/frontend/application/app/layout.tsx
index 211288c..0432385 100644
--- a/frontend/application/app/layout.tsx
+++ b/frontend/application/app/layout.tsx
@@ -1,9 +1,11 @@
import type { Metadata } from 'next';
+import Script from 'next/script';
import './globals.css';
import NextTopLoader from 'nextjs-toploader';
import ClientLayout from './ClientLayout';
import { getSeoConfig } from '../lib/seo';
import { vazirmatn, lalezar } from '../lib/fonts';
+import { generateOrganizationSchema } from '../lib/schema';
export async function generateMetadata(): Promise {
const config = await getSeoConfig();
@@ -43,6 +45,9 @@ export async function generateMetadata(): Promise {
authors: [{ name: brandName }],
creator: brandName,
publisher: brandName,
+ verification: config.googleSiteVerification ? {
+ google: config.googleSiteVerification,
+ } : undefined,
robots: isStaging ? {
index: false,
follow: false,
@@ -96,13 +101,13 @@ export async function generateMetadata(): Promise {
};
}
-import { generateOrganizationSchema } from '../lib/schema';
-
-export default function RootLayout({
+export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
+ const config = await getSeoConfig();
+
const orgSchema = generateOrganizationSchema({
name: 'کنینا ایران',
alternateName: 'Canina Iran (Canina pharma GmbH)',
@@ -144,9 +149,29 @@ export default function RootLayout({
const safeJsonLd = JSON.stringify([orgSchema, webSiteSchema]).replace(/
+ {/* Google Tag Manager (noscript fallback) */}
+ {isGtmEnabled && (
+
+ )}
+
{children}
+
+ {/* Google Tag Manager Script */}
+ {isGtmEnabled && (
+
+ )}
+
+ {/* Google Analytics 4 (GA4) Scripts */}
+ {isGaEnabled && (
+ <>
+
+
+ >
+ )}
+
+ {/* Microsoft Clarity Script */}
+ {clarityId && (
+
+ )}