پست

قطعی اینترنت بین‌الملل و سئو؛ چگونه هم رتبه گوگل را نگه داریم و هم کاربر ایرانی را؟

قطعی اینترنت بین‌الملل و سئو؛ چگونه هم رتبه گوگل را نگه داریم و هم کاربر ایرانی را؟

هر کسی که چند سال سایت ایرانی داشته باشد، دیر یا زود به این دوراهی می‌رسد: سرور را کجا قرار دهم؟ در شرایط عادی پاسخ ساده است، اما با قطعی اینترنت بین‌الملل هر انتخابی یک طرف ماجرا را فدا می‌کند. در این نوشته از پایه توضیح می‌دهم مشکل از کجا می‌آید، چه راه‌حل‌هایی وجود دارد، هر کدام چگونه کار می‌کند و در کجا دردسر می‌سازد.

مشکل اصلی چیست؟

وقتی اینترنت بین‌الملل قطع می‌شود، شبکه داخل ایران از بقیه دنیا جدا می‌ماند. سایت‌های داخلی برای کاربر ایرانی باز می‌مانند و سرورهای خارج از کشور در دسترس نیستند. نتیجه یکی از این دو حالت است:

محل سرورکاربر ایرانیGooglebot
خارج از ایراندسترسی ندارددسترسی دارد
داخل ایراندسترسی دارددسترسی ندارد

Googlebot ربات گوگل است که صفحه‌ها را می‌خواند و در فهرست جستجو (index) ثبت می‌کند. اگر چند بار پیاپی به صفحه‌ای نرسد، خطای crawl ثبت می‌شود و آن صفحه ممکن است از نتایج حذف شود. پس سرور فقط داخل ایران، سئو را به خطر می‌اندازد و سرور فقط خارج از ایران، کاربر را از دست می‌دهد. هدف این است که هر دو سطر جدول بالا را به حالت مطلوب برسانیم.

یک نکته را صادقانه بگویم. مستندات رسمی گوگل نمی‌گویند چند ساعت یا چند روز قطعی چه مقدار از رتبه را از بین می‌برد. این‌که قطعی کوتاه خطر کمتری از قطعی طولانی دارد، برداشت رایج میان سئوکاران است و قاعده‌ای از طرف گوگل نیست.

چهار راه‌حل

راه اول: دو URL جداگانه برای دو منطقه

یک نسخه روی سرور خارج با دامنه اصلی قرار می‌گیرد و نسخه‌ای دیگر روی سرور ایران، با زیردامنه یا مسیر جداگانه، مثلاً ir.example.com. این دو نسخه با hreflang به هم معرفی می‌شوند تا گوگل بداند هر کدام برای چه مخاطبی است.

خود گوگل در مستندات صفحه‌های وابسته به منطقه (locale-adaptive) همین را توصیه می‌کند: برای هر منطقه URL جداگانه و علامت‌گذاری با rel="alternate" hreflang (How Google Crawls Locale-Adaptive Pages).

  • مزیت: رفتار شفاف است و خطر cloaking وجود ندارد.
  • عیب: کاربری که از نتایج گوگل وارد نسخه خارج شود، در زمان قطعی به آن دسترسی ندارد. نگهداری دو نسخه هم هزینه دارد.
  • هشدار: گوگل در سیاست‌های اسپم خود، ساخت چندین دامنه یا صفحه برای مناطق مختلف که کاربر را به یک صفحه هدایت کنند را «doorway abuse» می‌نامد (Spam policies). نسخه‌ها باید هر کدام محتوای واقعی و مفید داشته باشند.

راه دوم: یک URL و مسیریابی بر اساس کشور

دامنه یکی است و جلوی سرورها لایه‌ای قرار می‌گیرد (CDN، reverse proxy یا load balancer) که کشور درخواست‌دهنده را تشخیص می‌دهد:

  • درخواست از ایران به سرور ایران می‌رود.
  • درخواست از سایر کشورها، از جمله Googlebot، به سرور خارج می‌رود.

نام عمومی این روش geo-based routing است. برخی سرویس‌دهندگان CDN داخلی هم قابلیتی مشابه را با نام‌های خودشان ارائه می‌کنند، مثلاً قوانین origin بر اساس کشور.

نکته مهم اینجاست که Googlebot را باید با IP تشخیص داد، نه با User-Agent. گوگل توضیح می‌دهد که IPهای پیش‌فرض Googlebot آمریکایی به نظر می‌رسند و درخواست‌هایش هدر Accept-Language ندارد. به همین دلیل ممکن است همه نسخه‌های یک سایت وابسته به منطقه خزش، ایندکس و رتبه‌بندی نشوند. گوگل از IPهای خارج از آمریکا هم خزش می‌کند و قاعده‌اش این است که اگر Googlebot از کشوری آمده، با آن مانند هر کاربر دیگر از همان کشور رفتار شود. برای تأیید هویت این درخواست‌ها هم می‌توان از reverse DNS استفاده کرد. یک نکته دیگر این‌که robots.txt و متاتگ‌های robots باید در همه نسخه‌ها قواعد یکسانی داشته باشند (منبع).

برای Googlebot نباید استثنای جداگانه تعریف کرد. چنین استثنایی دقیقاً همان کاری است که به cloaking شباهت پیدا می‌کند.

راه سوم: سرور ایران با کش قوی در CDN

سایت روی سرور ایران است و یک CDN جلوی آن قرار می‌گیرد. Googlebot نسخه کش‌شده را از لبه‌های خارج از ایران دریافت می‌کند. برای سایت‌های محتوایی این ساده‌ترین راه است، اما دو شرط دارد:

  1. محتوا باید عملاً ایستا باشد.
  2. CDN باید در صورت نبود دسترسی به origin، نسخه قدیمی کش را تحویل دهد. دستور stale-if-error در RFC 5861 دقیقاً برای همین تعریف شده است، ولی فقط وقتی فعال می‌شود که با خطای 500، 502، 503 یا 504 روبه‌رو شویم (RFC 5861). این سند در دسته Informational قرار دارد و استاندارد رسمی نیست. پشتیبانی هر CDN از آن را باید در مستندات همان سرویس بررسی کرد.

ضعف این روش آن است که خود CDN هم باید در زمان قطعی بتواند به origin داخل ایران برسد. این موضوع را باید پیش از اتکا به آن آزمایش کرد.

راه چهارم: معماری استاتیک‌محور

صفحه‌های عمومی (مقاله، دسته‌بندی، صفحه محصول) با SSG ساخته می‌شوند، یعنی خروجی HTML ایستا در زمان build. همین خروجی هم روی سرور ایران و هم روی سرور خارج منتشر می‌شود. بخش‌های پویا مانند سبد خرید، پنل کاربری و پرداخت فقط در ایران می‌مانند.

چون فقط فایل‌های ایستا تکثیر می‌شوند، نیازی به همگام‌سازی دیتابیس میان دو کشور نیست. همگام‌سازی دیتابیس بین دو دیتاسنتر خطر ناسازگاری داده و رکوردهای تکراری دارد و بهتر است از آن پرهیز شود. اگر پشته فنی سایت Nuxt، Next یا Astro باشد، این روش تمیزترین و کم‌دردسرترین گزینه است.

خطر اصلی: Cloaking

گوگل cloaking را اسپم می‌داند. تعریفش این است: نمایش محتوای متفاوت به کاربر و موتور جستجو، با قصد دستکاری رتبه و گمراه کردن کاربر. مثال‌های رسمی هم از جنس نمایش صفحه‌ای درباره مقاصد گردشگری به موتور جستجو و صفحه‌ای درباره دارو به کاربر هستند (Spam policies).

عبارت «با قصد» اهمیت دارد. تفاوت جغرافیایی که برای رساندن سایت به کاربر طراحی شده، به‌تنهایی نقض نیست. اما اگر نسخه خارج با نسخه ایران تفاوت جدی داشته باشد، گوگل چیزی را می‌بیند که کاربر نمی‌بیند و این وضعیت باید به هر قیمتی از آن پرهیز شود.

قواعدی که خودم رعایت می‌کنم:

  • متن، تیتر، لینک‌ها و داده ساختاریافته (structured data) در هر دو نسخه یکسان باشد.
  • مسیریابی فقط بر اساس IP و کشور انجام شود، نه User-Agent.
  • نسخه خارج هرگز از یک بازه مشخص قدیمی‌تر نباشد. با هر انتشار مطلب جدید، یک pipeline خودکار نسخه خارج را هم به‌روز می‌کند.
  • قیمت و موجودی یا در نسخه ایستا نمایش داده نشود، یا همان منطق نسخه ایران را داشته باشد.

مستندات رسمی گوگل درباره سناریوی قطعی اینترنت ایران چیزی نگفته‌اند. این قواعد برداشت خودم از اصول کلی گوگل هستند و تضمین رسمی ندارند.

نمونه پیاده‌سازی ساده

نمونه زیر با Hono روی Cloudflare Workers نوشته شده و فقط ایده راه دوم را نشان می‌دهد. مقدار request.cf.country در Workers از روی IP مشتری تعیین می‌شود (مستندات Cloudflare).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Hono } from 'hono';

type Bindings = {
  IR_ORIGIN: string;
  GLOBAL_ORIGIN: string;
};

type CfRequest = Request & { cf?: { country?: string } };

const app = new Hono<{ Bindings: Bindings }>();

app.all('*', async (c) => {
  const country = (c.req.raw as CfRequest).cf?.country;
  const origin = country === 'IR' ? c.env.IR_ORIGIN : c.env.GLOBAL_ORIGIN;

  const url = new URL(c.req.url);
  const target = new URL(url.pathname + url.search, origin);

  return fetch(new Request(target, c.req.raw));
});

export default app;

پیش از استفاده جدی، دو مورد را باید آزمایش کرد. نخست این‌که Worker در شرایط واقعی به origin داخل ایران وصل می‌شود یا نه. دوم این‌که در زمان قطعی، درخواست کاربر ایرانی اصلاً به لبه Cloudflare می‌رسد یا نه. اگر ترافیک ایران به آن لبه نرسد، کل ایده برای کاربر داخلی بی‌اثر است. من این سناریو را در قطعی واقعی نیازموده‌ام و نمی‌توانم برایش تضمین بدهم.

ترفندهای اجرایی

  • GeoDNS را تنها تکیه‌گاه قرار ندهید. تشخیص مکان در DNS به اطلاعات زیرشبکه کاربر (EDNS Client Subnet) وابسته است و همیشه دقیق نیست. تصمیم‌گیری در لایه HTTP، پشت CDN یا proxy، معمولاً قابل‌اعتمادتر است.
  • یک کلید فعال و غیرفعال بسازید. اگر مسیریابی جغرافیایی را به صورت قانونی قابل خاموش و روشن پیاده‌سازی کنید، در شرایط عادی همه چیز به سرور اصلی می‌رود و فقط در زمان بحران آن را فعال می‌کنید.
  • IP لبه CDN را در فایروال هر دو سرور مجاز کنید. اشتباه رایج این است که یکی از originها فقط IP کاربران را می‌پذیرد و درخواست خود CDN را رد می‌کند.
  • Search Console را زیر نظر بگیرید. با ابزار URL Inspection ببینید گوگل دقیقاً چه چیزی از صفحه دریافت می‌کند و گزارش Crawl Stats روزهای قطعی را با روزهای عادی مقایسه کنید.
  • Sitemap و canonical را یکدست نگه دارید. هر دو نسخه باید به یک آدرس canonical اشاره کنند و sitemap فقط یک نسخه از هر URL را معرفی کند.
  • robots.txt را در همه نسخه‌ها یکسان کنید. گوگل صراحتاً این را توصیه می‌کند.
  • پیش از بحران آزمایش کنید. با VPN دارای خروجی ایران و خروجی اروپا بررسی کنید هر طرف کدام نسخه را می‌گیرد.

کدام راه برای من مناسب است؟

نوع سایتپیشنهاد
وبلاگ یا سایت محتواییراه چهارم، یا راه سوم در صورت ترافیک کم
فروشگاه یا سایت پویاراه دوم، همراه با نسخه ایستا از صفحه‌های عمومی روی سرور خارج
سایتی که شفافیت کامل می‌خواهدراه اول همراه با hreflang

هیچ‌کدام از این راه‌ها جادویی نیست. هر یک چیزی را فدا می‌کند: سادگی، هزینه یا شفافیت. مهم این است که پیش از وقوع بحران تصمیم گرفته شود و راه انتخاب‌شده آزمایش شده باشد.