سئو تکنیکال سایت بزرگ | معماری بقا در گوگل – طاها سئو

زمستان ۹۹ بود. مدیر فنی یکی از بزرگ‌ترین خبرگزاری‌های ایران با من تماس گرفت. می‌گفت: «طاها، سایت ما ۴ میلیون صفحه دارد. هر روز ۲ هزار خبر جدید منتشر می‌کنیم. ولی گوگل فقط ۴۰٪ صفحاتمان را ایندکس می‌کند. سرعت سرور افتضاح است و هر Core Update که می‌آید، ۲۰٪ ترافیکمان نوسان می‌کند. انگار که گوگل ما را نمی‌شناسد.»

وقتی به لاگ سرورها و Search Console شان نگاه کردم، یک فاجعهٔ خاموش دیدم: ربات گوگل هر روز ۱.۵ میلیون صفحه را کرال می‌کرد که ۸۰٪ آن صفحات بی‌ارزشی مثل آرشیو تاریخ‌های قدیمی، برچسب‌های تکراری، نسخه‌های پرینت و صفحات جستجوی داخلی بودند. بودجهٔ کرال در حال سوختن بود و صفحات تازه، هرگز نور گوگل‌بات را نمی‌دیدند. به او گفتم: «شما یک کتابخانهٔ ملی هستید که راهروهایش پر از راهنماهای اشتباه است و گوگل به جای رفتن به مخزن اصلی، در انباری گم شده.»

۶ ماه بعد، صفحات ایندکس‌شده از ۱.۶ میلیون به ۳.۲ میلیون رسید، ترافیک ارگانیک ۶۵٪ رشد کرد، و بودجهٔ کرال بهینه شد. این مقاله، عصارهٔ همان پروژه و ده‌ها پروژهٔ عظیم دیگر است. سئوی تکنیکال برای سایت‌های بزرگ، مثل طراحی خیابان‌های یک کلان‌شهر است. اگر نقشه‌ات اشتباه باشد، با بهترین ماشین‌ها هم به مقصد نمی‌رسی.


فاز صفر: درک ابعاد فاجعه – ممیزی تکنیکال یک سایت عظیم

برای یک سایت بزرگ (بالای ۱۰۰ هزار صفحه)، سئوی تکنیکال دیگر با چک‌لیست‌های ۲۰ موردی حل نمی‌شود. اینجا باید مثل یک معمار داده فکر کنی.

۱. لاگ آنالیز، نبض نامرئی گوگل

اولین کاری که در پروژهٔ خبرگزاری کردم، گرفتن فایل‌های لاگ سرور (Raw Access Logs) ۷ روز اخیر بود. این فایل‌ها نشان می‌دهند گوگل‌بات دقیقاً چه URL هایی را، چه زمانی، و با چه Status Code ای کرال کرده است. من یک اسکریپت Python دارم که این لاگ‌ها را پارس می‌کند و گزارش می‌دهد:

  • چه صفحاتی بیشترین درخواست کرال را دارند (و آیا این صفحات ارزشمندند؟)

  • چه صفحاتی اصلاً کرال نمی‌شوند.

  • درخواست‌های با Status Code 500، 404 و 301.

  • نسبت کرال صفحات HTML به فایل‌های CSS/JS (آیا گوگل می‌تواند رندر کند؟)

در آن خبرگزاری، متوجه شدم که ۶۰٪ بودجهٔ کرال صرف صفحاتی مثل /tag/ و /date/2020/01/01/ می‌شود که ارزش سئویی صفر داشتند. در حالی که دسته‌بندی‌های اصلی خبری (با عمق ۴-۵ کلیک) کمتر از ۲٪ بودجه را می‌گرفتند.

۲. کرال آزمایشی در مقیاس

با Screaming Frog نمی‌شوی ۴ میلیون صفحه را کرال کنی. اینجا ابزارهای ابری مثل OnCrawl، Botify یا DeepCrawl (حالا Lumar) به کار می‌آیند. اگر بودجه نداری، می‌توانی با Sitebulb روی یک سرور قدرتمند، میلیون‌ها صفحه را کرال کنی. ولی خودم ترجیح می‌دهم با Python کتابخانهٔ scrapy را به کار بگیرم و یک خزندهٔ سفارشی بسازم که فقط ساختار URL ها، تایتل‌ها، Canonical و لینک‌های داخلی را استخراج کند. این روش انعطاف بی‌نهایتی دارد.


قدم اول: بهینه‌سازی بودجهٔ کرال – از گوگل یک محافظ بساز

بودجهٔ کرال یعنی تعداد صفحاتی که گوگل‌بات تصمیم می‌گیرد در یک روز از سایتت بخواند. اگر سایت ۴ میلیون صفحه‌ای داشته باشی و بودجهٔ روزانه‌ات ۱۰۰ هزار باشد، و ۸۰ هزارت صرف آرشیوهای بی‌ارزش شود، یعنی صفحات طلایی‌ات هرگز دیده نمی‌شوند.

۱. هرس بی‌رحم محتوا با noindex

باید شجاع باشی. صفحاتی را که هیچ ترافیک و ارزشی ندارند، یا noindex کن یا کلاً حذف. برای خبرگزاری، تصمیمات زیر را گرفتیم:

  • آرشیوهای تاریخ (مثلاً /2021/05/): همه noindex, follow شدند تا لینک‌های داخلی حفظ شود، ولی خودشان ایندکس نشوند.

  • برچسب‌ها (Tags): اگر تعداد برچسب‌ها بیش از ۵۰ هزار بود و هرکدام کمتر از ۳ خبر داشتند، noindex.

  • صفحات جستجوی داخلی: همیشه noindex و در robots.txt هم Disallow.

  • نسخه‌های پرینت، AMP قدیمی، RSS فید کامل: noindex.

۲. بهینه‌سازی robots.txt در مقیاس بزرگ

فقط disallow کردن کافی نیست. باید از Crawl-delay هوشمندانه استفاده کنی، اما گوگل‌بات دیگر از آن پشتیبانی نمی‌کند. در عوض، با نرخ کرال (Crawl Rate) در Search Console تنظیم کن. به گوگل بگو می‌تواند سریع‌تر کرال کند (اگر سرورت می‌کشد). در آن پروژه، بعد از بهینه‌سازی سرور، نرخ کرال را از حالت «محدود» به «بالا» بردیم و بعد از یک ماه، گوگل روزانه ۱.۸ میلیون صفحه می‌زد.

۳. ساختار لینک داخلی: به گوگل بگو چه چیزی مهم است

در یک سایت بزرگ، لینک‌های داخلی تنها ابزار تو برای توزیع بودجهٔ کرال هستند.

  • صفحهٔ اصلی: فقط به ۱۰-۲۰ دستهٔ اصلی لینک بدهد. نه به ۵۰۰ دامنه مختلف.

  • صفحات دسته‌بندی اصلی: به زیردسته‌ها و مهم‌ترین مطالب آن دسته لینک بدهند (نه لزوماً تازه‌ترین‌ها). از نمایش تصادفی خودداری کن. با یک الگوریتم بر اساس ترافیک و اهمیت، انتخاب کن.

  • صفحات محتوا: به نهایتاً ۵-۱۰ صفحهٔ مرتبط لینک بدهند (نه ۵۰ لینک در سایدبار و فوتر).

ما برای خبرگزاری، ماژول «مطالب مرتبط» را بازنویسی کردیم تا فقط مقالاتی را نشان دهد که از نظر معنایی به هم نزدیکند و ترافیک گرفته‌اند، نه صرفاً بر اساس تگ.


قدم دوم: شکست دادن محتوای تکراری در مقیاس وب

در سایت‌های بزرگ، محتوای تکراری مثل مورچه‌های ریز زیر سنگ‌هاست. باید سیستمیک حلش کنی.

۱. URL های پارامتری و Faceted Navigation

اگر سایتت فیلتر دارد (مثل فروشگاه‌ها یا جستجوی پیشرفته)، فاجعه در کمین است. برای خبرگزاری، پارامترهای اشتراک‌گذاری (?utm_source) و مرتب‌سازی (?order=comment) هزاران URL اضافی ساخته بود.

  • با rel="canonical" همه را به نسخهٔ اصلی برگردان.

  • در Search Console پارامترهای بی‌ارزش را «نادیده بگیر».

  • در htaccess. یا Nginx در صورت امکان پارامترهای غیرضروری را با ۳۰۱ حذف کن (اما مراقب باش).

۲. زیردامنه‌ها و پروتکل‌های مختلف

مطمئن شو که فقط یک نسخه از سایت وجود دارد:

  • تمام ترافیک http:// به https:// برود.

  • تمام ترافیک www به non-www (یا برعکس) ۳۰۱ شود.

  • هیچ محتوایی روی /staging. یا /dev. در معرض ایندکس نباشد. اگر هست، با Basic Auth یا noindex ببندش.


قدم سوم: سرعت در مقیاس – وقتی میلی‌ثانیه‌ها میلیون‌ها بار ضرب می‌شوند

برای یک سایت بزرگ، یک تأخیر ۳۰۰ میلی‌ثانیه‌ای در پاسخگویی دیتابیس، اگر ضربدر ۵ میلیون درخواست روزانه شود، یعنی نابودی.

۱. معماری سرور: هیچ چیز مثل یک هاست خوب نیست

خبرگزاری را از یک سرور اختصاصی قدیمی به یک کلاستر ابری با Load Balancer و PHP-FPM بردیم. نتیجه: Time To First Byte از ۱.۲ ثانیه به ۲۰۰ میلی‌ثانیه رسید.

۲. کشینگ چندلایه

  • CDN: قطعاً ArvanCloud یا Cloudflare برای عکس‌ها، CSS و JS. برای یک سایت خبری، تصاویر ۷۰٪ ترافیک را می‌سازند.

  • Page Cache: با Varnish یا Nginx FastCGI Cache، صفحات ایستا را در حافظه نگه دار. برای وردپرس، افزونه‌هایی مثل WP Rocket با Redis Object Cache.

  • Object Cache (Redis/Memcached): نتایج کوئری‌های تکراری دیتابیس را کش کن. این برای ویجت‌های «مطالب پربازدید» که هزاران بار در روز تکرار می‌شوند، واجب است.

۳. تصاویر: پردازش خودکار با اسکریپت

نمی‌شوی میلیون‌ها عکس را دستی بهینه کنی. یک اسکریپت Python نوشتم که با کتابخانهٔ Pillow، تمام عکس‌های جدید را در لحظهٔ آپلود به WebP تبدیل کند و ابعاد Responsive بسازد. همچنین lazy loading بومی (loading="lazy") را روی همهٔ تگ‌های <img> اعمال کردیم. LCP در موبایل از ۶.۸ به ۱.۹ ثانیه رسید.

۴. بودجهٔ جاوااسکریپت

در یک سایت بزرگ، اسکریپت‌های Third-party (تبلیغات، آنالیتیکس، چت) می‌توانند قاتل سرعت باشند. همه را با defer و async لود کن. اسکریپت‌های غیرحیاتی را تأخیری بارگذاری کن (مثلاً ویجت چت ۳ ثانیه بعد از لود صفحه). برای خبرگزاری، با تعویق یک اسکریپت تبلیغاتی سنگین، LCP ۴۰۰ میلی‌ثانیه بهبود یافت.


قدم چهارم: داده‌های ساختاریافته (Schema) در مقیاس – یک ارتش منظم بساز

برای ۴ میلیون صفحه، نمی‌شوی Schema را دستی بنویسی. باید اتوماتیک باشد.

  • Article Schema برای خبرگزاری: با یک قالب PHP، به‌طور خودکار headline، datePublished، dateModified، author (از دیتابیس)، image و publisher را پر کردیم. خبرگزاری‌ها با NewsArticle می‌توانند در Google News هم رتبه بگیرند.

  • BreadcrumbList برای همهٔ صفحات محتوا و دسته‌بندی.

  • Organization Schema در صفحهٔ اصلی با لوگو و شبکه‌های اجتماعی.

  • حتماً با Rich Results Test نمونه‌ها را چک کن. یک خطای کوچک در قالب می‌تواند میلیون‌ها خطا در Search Console تولید کند.

  • نکته: اگر میلیون‌ها صفحه داری، از JSON-LD استفاده کن، چون به DOM کاری ندارد و سبک‌تر از Microdata است.


قدم پنجم: سایت‌های بین‌المللی و hreflang – وقتی مرزها را درمی‌نوردی

اگر سایتت چندزبانه یا چندکشوری است (مثلاً site.com/fa/ و site.com/en/)، بدون hreflang، گوگل اینها را محتوای تکراری فرض می‌کند. برای یک شرکت هواپیمایی که سایتش ۴ زبان داشت، یک سیستم خودکار نوشتم:

  • با یک آرایه در PHP، زبان‌ها و URL های جایگزین استخراج می‌شد.

  • تگ‌های <link rel="alternate" hreflang="fa" href="..."> در <head> همهٔ صفحات تولید شد.

  • در نقشهٔ سایت هم xmlns:xhtml را اضافه کردیم.

  • خطاهای hreflang را با Search Console (بخش International Targeting) رصد کردیم. یکبار یک /fa/ اشتباهاً به جای /fa-ir/ ریدایرکت شده بود و گوگل hreflang را نادیده می‌گرفت. با اصلاح آن، ترافیک بین‌المللی ۳۰٪ رشد کرد.


قدم ششم: پایش و هشداردهی در مقیاس – چشمانی که هرگز نمی‌خوابند

برای یک سایت ۴ میلیون صفحه‌ای، نمی‌شوی هر روز Search Console را دستی نگاه کنی. من یک سیستم نظارت خودکار با Python ساختم:

  • اسکریپت ۱: هر ۶ ساعت، گزارش Coverage از Search Console API می‌گیرد و تغییرات ناگهانی در «صفحات ایندکس‌شده» و «خطاهای ۵۰۰» را چک می‌کند. اگر خطاها بیش از ۵٪ افزایش یابد، پیامک می‌فرستد.

  • اسکریپت ۲: هر شب، ۵۰ URL تصادفی از نقشهٔ سایت را می‌گیرد و با PageSpeed Insights API تست می‌کند. اگر امتیاز Core Web Vitals پایین بیاید، هشدار.

  • اسکریپت ۳: روزانه لاگ سرور را پارس می‌کند و نسبت کرال صفحات HTML به ریدایرکت/۴۰۴ را چک می‌کند. یکبار این اسکریپت نشان داد که به‌خاطر یک خطای برنامه‌نویسی، ۲۰۰ هزار URL یکشبه ۴۰۴ شده‌اند. همان شب قبل از اینکه گوگل بفهمد، با یک ریدایرکت دسته‌ای درستش کردیم.


یک مطالعهٔ موردی واقعی: خبرگزاری ملی (همان ابتدای مقاله)

وضعیت اولیه:

  • ۴ میلیون صفحه، بودجهٔ کرال روزانه ۱.۵ میلیون.

  • ۶۰٪ بودجه صرف صفحات بی‌ارزش (برچسب‌ها، آرشیو تاریخ، صفحات پرینت، جستجوی داخلی).

  • ۱.۶ میلیون صفحه ایندکس‌شده، LCP ۶.۸ ثانیه، Core Web Vitals قرمز.

  • نوسان ۲۰٪ ترافیک با هر Core Update.

اقدامات:

  1. لاگ آنالیز و شناسایی قاتلان بودجه (با Python).

  2. استراتژی noindex: ۱.۲ میلیون صفحه کم‌ارزش noindex شدند (برچسب‌ها، آرشیوهای قدیمی، نسخه‌های پرینت).

  3. بازسازی لینک داخلی: حذف لینک‌های تصادفی و جایگزینی با ماژول «مطالب مرتبط» بر اساس ترافیک و شباهت معنایی.

  4. بهبود سرعت: مهاجرت به کلاستر ابری، Redis، CDN، تبدیل خودکار عکس‌ها به WebP، تعویق اسکریپت‌های تبلیغاتی. LCP به ۱.۹ ثانیه رسید.

  5. Schema: پیاده‌سازی خودکار NewsArticle و BreadcrumbList برای همهٔ مقالات.

  6. تنظیم نرخ کرال روی حالت بالاتر.

  7. ریدایرکت‌ها: اصلاح ۸۰ هزار URL شکستهٔ قدیمی و ریدایرکت به نسخهٔ اصلی.

نتایج پس از ۶ ماه:

معیارقبلبعد
صفحات ایندکس‌شده۱.۶ میلیون۳.۲ میلیون
بودجهٔ کرال مؤثر (صفحات باارزش)۴۰٪۸۵٪
ترافیک ارگانیک ماهانه۵.۸ میلیون۹.۶ میلیون (+۶۵٪)
LCP موبایل۶.۸s۱.۹s
نوسان در Core Updates۲۰٪+< ۵٪

مدیر فنی بعد از ۶ ماه به من گفت: «طاها، تو خیابون‌های شهر ما را یک‌طرفه کردی. حالا گوگل مستقیم می‌رود به مقصد.»


نتیجه‌گیری: برای گوگل یک شهروند درجه یک شو

سایت‌های بزرگ مثل یک اقیانوس‌اند. نمی‌شود با یک سطل آب را تخلیه کرد. سئوی تکنیکال در این ابعاد، یعنی طراحی سیستم‌هایی که خودشان خطاها را پیدا کنند، محتوا را اولویت‌بندی کنند، و مسیر را برای ربات‌ها هموار سازند. نه با شعار، که با کد. ترکیب دانش سئو با قدرت Python و فهم عمیق از زیرساخت، تنها راه زنده ماندن در این بازی است.

من طاها هستم. ۱۵ سال است که با کد، لاگ و Logic، گره‌های غول‌های وب را باز می‌کنم. اگر وب‌سایت بزرگت دچار سندروم «گمشده در گوگل» شده، با طاها حرف بزن. نه برای یک گزارش PDF، که برای یک جراحی تکنیکال واقعی که سایتت را از یک غریبه به یک شهروند محترم گوگل تبدیل کند. یک جلسه مشاوره می‌تواند معماری ایندکس سایتت را برای همیشه اصلاح کند.

ارسال دیدگاه شما