PWA بودن هیچ امتیاز ویژهای در SEO ایجاد نمیکند. اگر هر نمای مهم URL مستقیم، HTML معنادار، Status درست و لینک قابل Crawl نداشته باشد، نصبپذیری، Push notification و Offline mode مشکل کشف را حل نمیکنند. از طرف دیگر، یک PWA میتواند دقیقاً مانند هر سایت خوب ایندکس شود—به شرطی که معماری App را با قراردادهای وب هماهنگ کنید.
پاسخ کوتاه: برای سئو PWA، محتوای عمومی را ترجیحاً با SSR، SSG یا Prerender در HTML اولیه بدهید؛ هر View را به URL پایدار و پاسخ مستقیم وصل کنید؛ Routing را با History API و لینک واقعی بسازید؛ Canonical/Meta/Status را روی Server درست کنید؛ Service Worker را بر اساس Freshness داده طراحی و نتیجه را در Raw HTML، Rendered DOM و URL Inspection تست کنید.
تست پنجدقیقهای: یک URL داخلی PWA را در پنجره ناشناس و با JavaScript غیرفعال باز کنید، سپس Source و Status را ببینید. اگر فقط یک App shell خالی با ۲۰۰ میگیرید و همه Routeها همان Title/Canonical را دارند، پیش از تولید محتوا مشکل معماری دارید.
PWA چیست و چه ارتباطی با SEO دارد؟
Progressive Web App یک «نوع ایندکس» نیست؛ مجموعهای از قابلیتهای وب است که میتواند نصب، Offline/Flaky-network experience، Background work و تجربه App-like را ممکن کند. قابلیتها بین مرورگر و سیستمعامل یکسان نیستند، پس Progressive enhancement لازم است.
SEO همچنان از قراردادهای وب پیروی میکند:
- هر محتوای عمومی یک URL قابل درخواست دارد؛
- Server پاسخ HTTP معنادار میدهد؛
- محتوا و Link در HTML/DOM قابل فهماند؛
- Indexing، Canonical و Robots کنترل میشوند؛
- Page experience برای کاربر واقعی مناسب است؛
- محتوا مفید و متناسب با Intent است.
Manifest و Service Worker میتوانند تجربه محصول را بهتر کنند، اما جای Title، H1، Internal link یا HTML قابل Crawl را نمیگیرند.
خط لوله Google برای JavaScript را بشناسید
Google Search فرایند Crawl، Render و Index را جدا توضیح میدهد. Googlebot ابتدا URL و پاسخ را میگیرد، Linkها را از HTML استخراج میکند و صفحه میتواند برای Render شدن در صف قرار گیرد. Chromium جاوااسکریپت را اجرا و DOM رندرشده را دوباره پردازش میکند. این توانایی به معنی بیهزینه یا بیخطا بودن CSR نیست.
| مرحله | شکست PWA | مدرک |
|---|---|---|
| Discovery | Link فقط onclick یا fragment | Crawl و HTML link inventory |
| Fetch | Route داخلی ۴۰۴/۲۰۰ shell یا Redirect loop | Status و Header مستقیم |
| Render | Bundle/API/CORS/Timeout خطا | Rendered HTML و Console |
| Index | Canonical/Noindex/محتوای تکراری | URL Inspection و Index report |
| Serve | Intent/کیفیت/رقابت نامتناسب | Query، Page و SERP |
مشاهده صفحه در Browser توسعهدهنده فقط Render کاربر را ثابت میکند، نه Discovery، Status، Canonical یا Indexability را.
۱. Rendering architecture را بر اساس نوع صفحه انتخاب کنید
| مدل | HTML اولیه | مزیت | ریسک SEO/Operation |
|---|---|---|---|
| SSG | کامل در Build | ساده، سریع و Cacheable | Freshness و Build بزرگ |
| SSR | کامل در Request | داده تازه و Crawlable | Latency، ظرفیت و خطای Server |
| ISR/Revalidation | نسخه Static با Refresh | تعادل Freshness/هزینه | Stale window و Invalidation |
| Hydration/Islands | محتوا + JS تعامل | HTML قابل استفاده و App UX | Hydration mismatch و JS زیاد |
| CSR | App shell حداقلی | Client interaction ساده | وابستگی به Render و API |
| Dynamic rendering | نسخه متفاوت برای Bot | Workaround موقت | Complexity، Drift و Cloaking risk |
Google Dynamic Rendering را Workaround و نه راهکار پیشنهادی بلندمدت میداند و SSR، Static rendering یا Hydration را ترجیح میدهد. برای محتوای Public و Search-driven، HTML اولیه معنادار معمولاً Robustتر است. Dashboard پشت Login یا ابزار شخصی ممکن است CSR کاملاً مناسبی داشته باشد.
۲. برای هر View عمومی URL پایدار بسازید
Route فقط State داخلی App نیست. URL باید Bookmark، Share، Refresh، Back/Forward و درخواست مستقیم را درست پشتیبانی کند.
- برای محتوای مستقل Path واقعی مانند
/products/123بسازید. - از
#/productsبرای تغییر محتوای Indexable استفاده نکنید؛ Google History API را برای SPA routing توصیه میکند. - هر Route مستقیم باید همان محتوا را بدون عبور از Home باز کند.
- Query parameter را فقط برای State معنادار و کنترلشده بهکار ببرید.
- URL Session، Token، User ID یا State خصوصی را Indexable نکنید.
- Trailing slash، حروف، Encoding فارسی و Case را یکدست کنید.
Route map را با Method، Status، Canonical، Indexability و Owner نگه دارید.
۳. Navigation را با لینک HTML واقعی بسازید
Google Link را وقتی مطمئنتر کشف میکند که عنصر <a> با href داشته باشد. Button با onclick که Route را Push میکند، برای Action مناسب است؛ برای Navigation جای Anchor را نگیرد.
<a href="/products/کفش-دویدن">کفش دویدن</a>- Anchor text مقصد را توصیف کند؛
- Menu، Breadcrumb و Related links در DOM باشند؛
- Link به Route نامعتبر یا Redirect chain نرود؛
- Lazy component نباید Link discovery را به Scroll غیرممکن وابسته کند؛
- هر صفحه مهم از یک صفحه قابل کشف لینک بگیرد؛
- Sitemap مکمل Link graph است، نه جایگزین آن.
۴. Deep link و Status code را درست پاسخ دهید
پیکربندی رایج SPA همه مسیرها را با index.html و Status ۲۰۰ برمیگرداند. نتیجه میتواند Soft ۴۰۴ باشد: URL ناموجود همان shell را میگیرد و بعد Client پیام «یافت نشد» میسازد.
| سناریو | Status مطلوب | بدنه |
|---|---|---|
| محصول موجود | 200 | HTML محصول و Meta یکتا |
| محصول منتقلشده | ۳۰۱/۳۰۸ برحسب سیاست | Location مستقیم به معادل |
| محصول حذف و بیجایگزین | ۴۰۴ یا ۴۱۰ | صفحه خطای مفید |
| نیاز به ورود | Login/Access policy روشن | محتوای خصوصی Index نشود |
| خطای Server/API | 5xx/Retry منطقی | نه ۲۰۰ با Empty state |
Error boundary کاربر با پاسخ HTTP Server یکی نیست. هر دو را تست کنید.
۵. App shell باید محتوای اولیه معنادار داشته باشد
Skeleton screen میتواند UX را بهتر کند، اما اگر Raw HTML فقط Spinner، Root div و Script باشد، Link و محتوای اولیه به Render وابسته میشوند. برای Routeهای Search-driven حداقل Title، H1، متن اصلی، Linkهای مهم و Structured data را Server/Build تولید کنید.
Hydration نباید متن Server را حذف یا با Placeholder جایگزین کند. تفاوت HTML Server و Client را در CI مقایسه کنید.
۶. Title، Meta، Canonical و Robots را Route-aware کنید
هر Route باید Metadata خودش را داشته باشد و درخواست مستقیم همان Metadata را برگرداند.
- Title/H1: متمایز، هماهنگ و متناسب با Intent؛
- Meta description: خلاصه همان Route، نه متن Home؛
- Canonical: URL نهایی واقعی، نه Canonical همگانی به Root؛
- Robots: Index/Noindex بر اساس نوع صفحه؛
- Open Graph: برای Share مستقیم Route؛
- Language/Direction:
lang="fa"وdir="rtl"مناسب؛ - Hreflang: فقط برای نسخههای واقعی و متقابل.
تغییر Meta با JavaScript ممکن است پردازش شود، اما Server metadata خطاپذیری و Flash اشتباه را کم میکند. کنترلهای On-page را با چکلیست سئو داخلی صفحه بررسی کنید.
۷. Robots.txt نباید Resource لازم برای Render را ببندد
اگر JS، CSS یا API عمومی لازم برای ساخت محتوای Indexable Block شود، Render ناقص میشود. Robots را برای پنهانکردن Secret یا داده خصوصی بهکار نبرید؛ Resource حساس باید Authentication/Authorization داشته باشد.
- Bundleهای ضروری و API محتوای Public قابل Fetch باشند؛
- Staging با Authentication محافظت شود، نه فقط Disallow؛
- Route Noindex باید Crawl شود تا Rule دیده شود؛
- نسخه Hashشده Asset در Deploy قدیمی فوراً حذف نشود؛
- CORS و CSP درخواست Renderer را بیدلیل نشکنند.
۸. Service Worker را بر نوع Resource طراحی کنید
Service Worker درخواست Browser را Intercept و میتواند Cache را پیش از HTTP cache پاسخ دهد. Strategy واحد برای همه چیز خطرناک است.
| Resource | Strategy نمونه | قید |
|---|---|---|
| App shell نسخهدار | Cache first | Version و cleanup روشن |
| Article کمتغییر | Stale-while-revalidate | نمایش Update و TTL |
| Catalog/Price | Network first + fallback محدود | Timestamp و Stale warning |
| Order/Balance | Network only یا سیاست سخت | داده خصوصی Cache عمومی نشود |
| Image/Font versioned | Cache first | Quota و eviction |
| Offline fallback | Cache only | بهعنوان محتوای واقعی Index نشود |
مشکل Cache قدیمی بیش از همه تجربه کاربر و صحت داده را تهدید میکند. آن را خودکار به «Googlebot حتماً نسخه قدیمی میبیند» تعمیم ندهید؛ رفتار Fetch/Render را جدا با ابزار Google و Request مستقیم آزمایش کنید.
برای TTL، Freshness، Cache key، Stampede و Privacy از راهنمای معماری Cache سایت استفاده کنید.
۹. Update lifecycle و Invalidation را طراحی کنید
Service Worker جدید ممکن است Install شود اما تا بستهشدن Tabهای قدیمی Activate نشود. کاربر میتواند چند نسخه App را همزمان ببیند اگر Migration و پیام Update ضعیف باشد.
- Cache name و Asset manifest را Version کنید.
- Cacheهای قدیمی را در Activate با احتیاط پاک کنید.
- برای نسخه ناسازگار، پیام «نسخه جدید آماده است» و Refresh کنترلشده بدهید.
- API schema را با Client قدیمی سازگار یا Version کنید.
- Rollback App و Worker را تمرین کنید.
- Cache purge را در Runbook انتشار ثبت کنید.
- در Offline، زمان آخرین همگامسازی را نشان دهید.
۱۰. محتوای مهم را فقط با Interaction بار نکنید
Tab، Accordion و Client state اگر محتوای اصلی را پس از Click/API خاص بسازند، Discovery و Index را پیچیده میکنند. اطلاعات اصلی Route را در DOM اولیه/رندرشده قرار دهید.
- Infinite scroll یک مسیر Paginated یا URLable داشته باشد؛
- Load more بدون Link تنها مسیر کشف نباشد؛
- Product variant مهم URL/Canonical policy روشن داشته باشد؛
- Filterها Crawl space بینهایت نسازند؛
- Content پشت Consent یا Geolocation fallback متنی داشته باشد؛
- Canvas متن اصلی را جایگزین Semantic HTML نکند.
۱۱. Canonical و Facet را بر اساس ارزش Search تنظیم کنید
PWA فروشگاهی ممکن است برای Sort، Filter، Pagination و Campaign هزاران URL بسازد. برای هر نوع تصمیم بگیرید: Index، Canonical، Noindex، Crawl limit یا حذف Parameter.
| نوع | نمونه تصمیم | شرط |
|---|---|---|
| Category اصلی | Index self-canonical | محتوا و تقاضای مستقل |
| Sort | Canonical به Category | همان مجموعه، ترتیب متفاوت |
| Filter ارزشمند | Landing page کنترلشده | تقاضا، موجودی و متن مستقل |
| Filter ترکیبی بینهایت | محدودسازی Crawl/Index | ارزش کم و URL زیاد |
| Campaign parameter | Canonical پاک | محتوا یکسان |
Canonical hint است، Redirect نیست. Internal link و Sitemap را به URL ترجیحی بدهید تا Signalها سازگار باشند.
۱۲. Structured data را با محتوای Route هماهنگ کنید
JSON-LD باید نوع پشتیبانیشده، Property لازم و محتوای قابل مشاهده همان URL را منعکس کند. App shell نباید یک Schema ثابت را برای همه Routeها تکرار کند.
- Product/Article/Breadcrumb را Route-aware بسازید؛
- قیمت و موجودی Structured data با UI/API همگام باشد؛
- Schema Server و Client Duplicate یا متناقض نشود؛
- Rich Results Test و Rendered HTML را بررسی کنید؛
- وجود Schema نمایش Rich result را تضمین نمیکند.
۱۳. Web App Manifest را برای Product UX تنظیم کنید
Manifest شامل نام، Icon، Start URL، Display و اطلاعات نصب است. این فایل بهخودیخود رتبه صفحه را بالا نمیبرد، اما Install experience خراب میتواند اعتماد کاربر را کم کند.
start_urlبه Route پایدار و مجاز برود؛scopeRouteهای ناخواسته را نگیرد؛- Icon در اندازه و Masking لازم تست شود؛
- Name/Short name با برند یکسان باشد؛
- Deep link نصبشده به صفحه مورد انتظار باز شود؛
- پارامتر Attribution در Start URL Duplicate index نسازد.
۱۴. Core Web Vitals را با داده میدانی بسنجید
معیارهای فعلی Core Web Vitals شامل LCP، INP و CLS هستند؛ FID دیگر معیار جاری این مجموعه نیست. هدفهای مرجع web.dev در صدک ۷۵ عبارتاند از LCP حداکثر ۲٫۵ ثانیه، INP حداکثر ۲۰۰ میلیثانیه و CLS حداکثر ۰٫۱، با تفکیک Mobile/Desktop.
| Metric | ریسک رایج PWA | اقدام |
|---|---|---|
| LCP | Render-blocking JS و Hero Client-only | SSR/Preload/تصویر بهینه |
| INP | Main-thread task، Hydration و handler سنگین | Code split، Yield و کاهش JS |
| CLS | Skeleton/Font/Image بدون Dimension | Space reservation و Font strategy |
Lab برای Debug و Field/RUM برای تجربه واقعی است. Page experience مهم است اما نمره کامل، رتبه یک را تضمین نمیکند. وضعیت Cache گرم و نصبشده را از First visit جدا گزارش کنید.
۱۵. شبکه ضعیف و Offline را با صداقت طراحی کنید
Offline نباید داده مالی یا موجودی قدیمی را «زنده» نشان دهد. برای کاربر ایرانی که ممکن است با کیفیت شبکه متغیر روبهرو باشد، Stale state و Sync conflict باید واضح باشد.
- زمان آخرین Update را نمایش دهید؛
- Action آفلاین را Queue و وضعیت Pending را متمایز کنید؛
- Retry Idempotent باشد تا سفارش/فرم دوبار ثبت نشود؛
- Conflict resolution برای Edit همزمان تعریف کنید؛
- قیمت، موجودی و پرداخت بدون Network truth نهایی نشوند؛
- Offline fallback Status و مسیر بازگشت داشته باشد.
۱۶. Analytics در SPA را Route-aware کنید
Client navigation لزوماً Page view خودکار درست تولید نمیکند. Measurement باید Virtual page view، Referrer، Title، Consent و Duplicate event را کنترل کند.
- روی Route completion—not click—Page view بفرستید؛
- Hard load و Client transition را Double-count نکنید؛
- Offline queue را با Timestamp اصلی و Deduplication ارسال کنید؛
- Install/open را از Search landing جدا کنید؛
- خطای Render/API/Service Worker version را Dimension کنید؛
- Search Console Page/Query را با Analytics canonical URL همراستا کنید.
۱۷. Security و SEO را مقابل هم قرار ندهید
HTTPS برای Service Worker و امنیت انتقال ضروری است، اما PWA را امن کامل نمیکند. Token و Secret را در Bundle/Manifest/Cache نگذارید. Cache API و IndexedDB میتوانند داده حساس را روی دستگاه مشترک نگه دارند.
- CSP را با Report و Rollout کنترلشده تنظیم کنید؛
- Service Worker scope را حداقل نگه دارید؛
- Logout، Cache/Storage حساس را پاک کند؛
- API Authorization روی Server باشد؛
- Dependency و Build pipeline بهروزرسانی و Provenance داشته باشد؛
- Push permission را در Context و پس از ارزش درخواست کنید.
۱۸. سئوی بینالمللی و فارسی در PWA
Language switch نباید فقط State Client یا Local storage باشد. هر زبان Public URL مستقل، HTML و Hreflang متقابل داشته باشد. Redirect اجباری بر اساس IP/Browser میتواند Bot و کاربر را از انتخاب محروم کند.
- URL فارسی/انگلیسی پایدار و Canonical جدا؛
langوdirروی Document و Component درست؛- Font فارسی Subset و
font-displayمناسب؛ - Title/Meta/Schema ترجمه انسانی و Route-aware؛
- عدد، تاریخ، Currency و Input موبایل تست؛
- Cache key شامل Locale در صورت نیاز؛
- Offline bundle زبان درست را نگه دارد.
۱۹. Test matrix سئو PWA
| تست | ابزار/روش | Pass criteria |
|---|---|---|
| Raw response | curl/HTTP client | Status، H1/Content/Meta معنادار |
| Deep link | Incognito direct URL | همان View، بدون Home detour |
| JS disabled/failed | DevTools/Block script | محتوای اصلی یا fallback مفید |
| Rendered DOM | URL Inspection/Rich Results | Content، Link، Canonical یکسان |
| Routing | Back/Forward/Refresh/Share | URL و State درست |
| Status | Route موجود/حذف/خطا | ۲۰۰/3xx/۴۰۴/5xx واقعی |
| Cache | Warm/Cold/Offline/Update | Freshness و پیام درست |
| CWV | RUM + Lab | صدک ۷۵ و Regression budget |
| Index | Search Console | Canonical و Coverage مورد انتظار |
ممیزی جامع Crawl/Index/Canonical را با چکلیست SEO Audit تکمیل کنید.
۲۰. CI/CD و Release gate برای PWA
- Routeهای حیاتی را با Direct request و Snapshot HTML تست کنید؛
- Title/Canonical/Robots یکتا را Assert کنید؛
- Broken link و Orphan route را Crawl کنید؛
- Bundle budget و Long task را مانیتور کنید؛
- Service Worker install/activate/update/rollback را E2E تست کنید؛
- Schema و Sitemap را Validate کنید؛
- Staging را Noindex + Authentication و Production را Index policy درست بدهید؛
- Canary release و Rollback trigger داشته باشید.
HTTP/۳ ممکن است Transport را در برخی شبکهها بهتر کند، اما JavaScript و Render architecture را حل نمیکند. برای QUIC، UDP ۴۴۳، ۰-RTT و Fallback به راهنمای HTTP/۳ رجوع کنید.
۲۱. Monitoring پس از انتشار
| سیگنال | منبع | هشدار |
|---|---|---|
| Route availability | Synthetic direct URL | Status/Content marker اشتباه |
| Render/API error | RUM/Error tracking | افزایش بر Version/Route |
| SW version | Client telemetry | نسخه قدیمی طولانی |
| CWV | Field data | Regression صدک ۷۵ |
| Index/Canonical | Search Console | Excluded/Alternate غیرمنتظره |
| Traffic | Query/Page | افت پس از Deploy |
برای طراحی Check، SLO و Alert از راهنمای مانیتورینگ Uptime و SLO و برای اتصال Log/Metric/Trace/RUM از راهنمای Observability سایت استفاده کنید.
۲۲. تجربه کاربر نصبشده و Browser را جدا آزمایش کنید
کاربر نصبشده ممکن است Navigation، Window mode، Back behavior و Update متفاوتی ببیند. Search landing معمولاً در Browser شروع میشود. مسیر Browser → ارزش → دعوت نصب را بدون Interstitial مزاحم طراحی کنید.
- Install prompt را بلافاصله در اولین Load تحمیل نکنید؛
- Back و External link در Standalone mode قابل پیشبینی باشد؛
- Share target و Deep link داده را گم نکند؛
- Accessibility keyboard، focus و screen reader تست شود؛
- Push opt-in با رضایت و Unsubscribe روشن باشد.
برای Task flow، Accessibility و سنجش تجربه از راهنمای جامع UX کمک بگیرید.
نقشه ۳۰ روزه اصلاح سئو PWA
روز ۱ تا ۷: Baseline
- Route inventory، Status، Metadata و Indexability را خروجی بگیرید.
- ۱۰ URL را Raw/Rendered/Direct مقایسه کنید.
- Search Console، RUM و Error baseline بسازید.
روز ۸ تا ۱۴: Rendering و URL
- Routeهای Search-driven را SSR/SSG/Hybrid کنید.
- Fragment و onclick navigation را به URL/Anchor درست تبدیل کنید.
- ۴۰۴، Redirect، Canonical و Sitemap را اصلاح کنید.
روز ۱۵ تا ۲۱: Cache و Performance
- Resource-class strategy و Freshness policy بنویسید.
- SW update/rollback و Offline conflict را تست کنید.
- LCP/INP/CLS و Bundle budget را به Release gate وصل کنید.
روز ۲۲ تا ۳۰: QA و Monitor
- CI snapshot، Schema و Deep-link E2E را فعال کنید.
- Synthetic marker و Error/version telemetry بسازید.
- یک Deploy canary و Rollback drill اجرا کنید.
برای ممیزی Rendering، Service Worker، Core Web Vitals و Index میتوانید درخواست مشاوره فنی و SEO ثبت کنید.
سوالات متداول سئو PWA
آیا PWA بودن باعث بهبود رتبه Google میشود؟
خیر، PWA امتیاز رتبهبندی مستقل و تضمینی نیست. سرعت، تجربه، Crawlability و محتوای مفید میتوانند کمک کنند، اما Manifest یا نصبپذیری بهتنهایی رتبه نمیسازد.
آیا Google محتوای JavaScript را ایندکس میکند؟
Google میتواند JavaScript را Render کند، اما Resource blocked، API error، App shell خالی و Link نامناسب مشکل میسازند. HTML Server/Static برای محتوای عمومی Robustتر است و باید با URL Inspection تست شود.
SSR بهتر است یا CSR؟
برای Route عمومی و Search-driven، SSR/SSG/Hybrid معمولاً ریسک کمتری دارد. برای Dashboard پشت Login یا تعامل کاملاً شخصی، CSR میتواند مناسب باشد. تصمیم را بر نوع صفحه، Freshness و عملیات بگیرید.
آیا Service Worker محتوای قدیمی را به Googlebot میدهد؟
نباید چنین حکم عمومی داد. Cache strategy مستقیماً تجربه Browser را کنترل میکند؛ رفتار Google Fetch/Render را باید جدا آزمود. در هر حال، Freshness و نسخه قدیمی برای کاربر یک ریسک جدی است.
مهمترین تست قبل از انتشار PWA چیست؟
یک مجموعه URL حیاتی را مستقیم درخواست کنید و Status، Raw HTML، Rendered DOM، Title/Canonical/Robots، Link، Structured data و رفتار Cache/Offline را با نتیجه مورد انتظار مقایسه کنید.
جمعبندی
سئو PWA مسئله «فریبدادن Bot برای دیدن JavaScript» نیست؛ مسئله حفظ قراردادهای وب در یک App تعاملی است. URL پایدار، HTML معنادار، Status واقعی، Link قابل Crawl، Metadata Route-aware، Cache با Freshness روشن و Monitoring نسخهها پایهاند. PWA را برای کاربر بسازید، سپس هر مرحله Crawl، Render و Index را با مدرک جداگانه اثبات کنید.
منابع مرجع: Google JavaScript SEO Basics، Google درباره Dynamic Rendering، web.dev درباره Service Worker و HTTP Cache و web.dev درباره Core Web Vitals جاری.






