
آدرس کنونیکال (Canonical url) به مثابه هویت هر صفحه از وبسایت
یک صفحه ممکن است با آدرسهای متفاوتی در وبسایت شما نمایش داده شود. مانند شخصی که نامش در شناسنامه یک چیز است و در خانه طور دیگری صدایش میکنند. ماهیت آدرس کنونیکال (Canonical URL) در واقع این است که به موتورهای جستجو بگوید کدام URL نام سجلی صفحه است. اگر گذارتان به سایتی مثل استکاورفلو افتاده باشد و به آدرس صفحه دقت کرده باشید چیزی شبیه این عایدتان میشود:
stackoverflow.com/questions/79358785/how-can-i-ensure-two-grid-columns-are-equal-in-width-when-the-first-columns-con
قسمت آخر URL را که نگاه کنید قسمتی را میبینید که شما احتمالا به از من میدانید چیست. اسلاگ (Slug) بخش توصیفی و خوانای یک URL است که بهصورت مختصر، محتوای صفحه را معرفی میکند (و اغلب قریب به اتفاق عنوان اصلی صفحه است که با کمی تغییر در آدرس قرار میگیرد). این قسمت از آدرس هم به آدمها کمک میکند تا بدون دیدن صفحه بتوانند حدس بزنند که چه چیزی در آن صفحه انتظارشان را میکشد، هم به موتورهای جستجو در ایندکس کردن صفحه کمک میکند(و باعث بهبود سئوی صفحه در موتورهای جستجو میشود). با این اوضاف اگر در آدرس قبلی این قسمت انتهایی را حذف کنید میشود این آدرس:
stackoverflow.com/questions/79358785
روی لینک که کلیک کنید به همان صفحه قبلی منتقل میشوید با کد ۳۰۱ ریدایرکت (301 redirect). به کجا؟ به آدرس کنونیکال.

تا اینجا این روزی روزگاریها را به هم بافتم که برسم به مقصود اصلی این نوشتار.
مدیریت آدرسها با ریسپانس ۳۰۱ برای حفظ هویت صفحه
اسلاگها با وجودی که برای صفحه شما پیشِ موتورهای جستجو اعتبار میخرند اگر در صورت تغییر درست مدیریت نشوند شبیه چک بلامحلی میشوند که اعتبار سایت شما را زیر سوال میبرند و به قولی گوگل برایتان پنالتی در نظر میگیرد. اگر باز کمی دقت کنیم هربار که عنوان سوال در استکاورفلو تغییر میکند اسلاگ عوض میشود. اما شما اگر همان آدرس قبلی را بزنید با کد ریسپانس ۳۰۱ آدرس جدید منتقل میشوید و اینطوری هم کاربر متوجه تغییر نمیشود و هم به موتور جستجو میگوییم این صفحه همان صفحه قبلیاست. هویت با وجود تغییرات همان است که بود. پس بهتر آن است که همیشه فرض بگیریم آدرسها ممکن است تغییر کنند.
گرچه این ماجرا سادهاست؛ اما به قول معروف شیطان همیشه در جزئیات است. جزئیاتی که همیشه پشت گوش میاندازیم تا شاید روزی سراغشان برویم و سر آخر هم مدیریت نکردن همین چیزهای کوچک و ساده ممکن است فاصلههای زیاد را ایجاد کنند و معنا شوند.
کلید ساده ماجرا این است که شما همیشه صفحه را با آیدی جستجو کنید و اگر اسلاگ آنی نبود که توی دیتابیس شما ذخیره شده در جواب آدرس کنونیکال را با کد ۳۰۱ برگردانید. همین!
اگر کد شما از تمپلیت استفاده میکند همه چیز به سادگی میتواند اتفاق بیافتد:
Route::get('/posts/{id}/{slug?}', function ($id, $slug = null) { $post = Post::findOrFail($id); if ($slug !== $post->slug) { return redirect()->to('/posts/' . $post->id . '/' . $post->slug, 301); } return view('post.show', compact('post')); });
اگر هم دارید restAPI کار میکنید تغییر کوچک زیر همه چیز را حل میکند:
Route::get('/api/posts/{id}/{slug?}', function ($id, $slug = null) { $post = Post::findOrFail($id); if ($slug !== $post->slug) { return response()->json([ 'redirect_url' => url("/posts/{$post->id}/{$post->slug}") ], 301); } return response()->json($post); });
سمت کلاینت هم اگر در فرانتاند سرور رندرینگ (SSR) مانند Next.js استفاده شود کافیاست ریسپانس را سمت سرور چک کنید و اگر لازم بود ریدایرکت را با هدر لوکیشن انجام دهید:
if (response.status === 301) { const data = await response.json(); .href = data.redirect_url; }
موتورهای جستجو در صورت مشاهدهی این هدر و کد ۳۰۱ متوجه تغییر دائمی آدرس میشوند و اعتبار صفحه قبلی را به صفحه جدید منتقل میکنند. بدون این هدر، موتورهای جستجو ممکن است تغییر مسیر را شناسایی نکنند و محتوای صفحه را به عنوان محتوای تکراری (Duplicate Content) در نظر بگیرند.
در واقع هدر لوکیشن بخشی از استاندارد پروتکل HTTP است و برای ریدایرکتهای 3xx استفاده میشود. این هدر به همراه کد 3xx ارسال میشود و مرورگر را موظف میکند کاربر را به URL جدید ببرد.