افحص تناسق hreflang والروابط المتبادلة
لا تعمل مجموعات hreflang بصورة موثوقة إلا عندما تعلن كل صفحة مشاركة المجموعة الكاملة نفسها من البدائل، بما في ذلك الإحالة إلى ذاتها.
شغّل الأداة مجانًا
تقارن هذه الأداة التعيينات المجموعة من صفحات متعددة وتكشف المجموعات الناقصة من دون جلب أي URL. وهي تبني مجموعة الصفحات المتوقعة من جميع عناوين المصدر والوجهة، ثم تفحص كل مصدر وتعرض الروابط الدقيقة الناقصة في كل صفحة. النتيجة حتمية ومناسبة لفحوص النشر وعمليات الترحيل ومراقبة جودة SEO بصورة دورية.
أهمية اكتمال الإحالات المتبادلة
ليست إشارة hreflang توصية أحادية الاتجاه من صفحة إلى أخرى، بل تصف عضوية مجموعة من الصفحات المتكافئة بحسب اللغة أو المنطقة. ولذلك ينبغي لكل صفحة أن تنشر مجموعة الوجهات نفسها وأن تدرج نفسها أيضًا. فإذا ذكرت الصفحة الإنجليزية البديلين الفرنسي والألماني، بينما لم تذكر الفرنسية سوى الإنجليزية، ظلت المجموعة ناقصة ولو بدت عدة وسوم منفردة صحيحة. قد تتجاهل محركات البحث العلاقات غير المؤكدة، فتُظهر نسخة لغوية غير مناسبة أو تضعف الإشارة الإقليمية المقصودة. وتصبح المراجعة اليدوية أقل موثوقية كلما كبرت المجموعة لأن عدد العلاقات يرتفع بسرعة. تحتاج مجموعة من أربع صفحات إلى أن تعلن كل صفحة الوجهات الأربع، أي إلى ست عشرة علاقة بين المصدر والوجهة. تحول هذه الأداة المقارنة البصرية إلى اختبار مجموعات دقيق، ولا تقر الاتساق إلا عندما تعلن كل صفحة ممثلة جميع صفحات المجموعة، فتجعل حالات السهو والإحالات الذاتية الناقصة ظاهرة بوضوح.
إعداد التعيينات وقراءة النتائج
أرسلوا سجلًا واحدًا لكل إعلان hreflang رُصد. يحدد page_url الصفحة التي تحتوي الوسم، ويحفظ language قيمة الوسم، ويحدد target_url وجهته. أدرجوا سجلات جميع الصفحات التي يفترض أن تنتمي إلى المجموعة. تستخرج الأداة المجموعة المتوقعة من اتحاد عناوين المصدر والوجهة. لذلك إذا أشارت الصفحات النظيرة إلى صفحة لا تقدم أي إعلانات خاصة بها، فإنها تبقى ضمن المجموعة المتوقعة ويُبلّغ عن فقدانها جميع الوجهات. تقارن عناوين URL كنصوص متطابقة بعد حذف المسافات الخارجية، لذا ينبغي أن تستخدم عملية الجمع الصيغة المطلقة المعيارية التي تنتجها الصفحات. يتضمن الناتج ملخصًا لكل صفحة وقائمة بالتعارضات. تعرض الصفحة الناقصة في missing_urls الوجهات المحددة الواجب إضافتها. لا تكون consistent صحيحة إلا عندما تخلو قائمة التعارضات. ولا تصنع الإعلانات المكررة اكتمالًا زائفًا لأن الوجهات تُقارن بوصفها مجموعة.
الاستخدام في النشر والترحيل والتدقيق الدوري
أفضل وقت لفحص التبادلية هو قبل وصول برامج الزحف إلى إصدار متعدد اللغات. صدّروا إعلانات hreflang الناتجة من الصفحات المعروضة، وحولوها إلى سجلات تعيين، وأوقفوا النشر عندما تكون consistent خاطئة. يكشف ذلك فروع القوالب التي تغفل الصفحة الحالية، وإطلاق الأسواق الإقليمية الذي يحدث السوق الجديد وحده، وعمليات الترحيل التي تواصل فيها لغة ما إنتاج عناوين قديمة. يصلح الفحص أيضًا بعد إضافة اللغات أو إيقافها. ولأن الخوارزمية لا تنفذ طلبات شبكة، فهي لا تثبت أن الوجهة تستجيب أو أنها معيارية أو أن محتواها مكافئ؛ فتلك أمور تحتاج إلى زحف ومراجعة تحريرية منفصلين. وعد الأداة محدد وأقوى: تحديد ما إذا كانت كل صفحة ممثلة تسرد جميع الصفحات الأخرى ونفسها. تستخدم طلبات API السعر الأساسي المنشور البالغ $0.002، ويمكن للمتصفح تنفيذ المقارنة النقية نفسها محليًا. احفظوا التعارضات مع أدلة النشر كي يرتبط كل تصحيح بمصدر ووجهة محددين بدل تحذير عام.
حالات الاستخدام
التحقق من إطلاق متعدد اللغات
تحققوا قبل النشر من أن كل لغة جديدة وكل صفحة نظيرة قائمة تعلن المجموعة الكاملة من البدائل.
تدقيق ترحيل منصة
قارنوا تعيينات القوالب الجديدة وحددوا الصفحات التي فقدت الإحالة الذاتية أو روابط العودة أثناء الترحيل.
حماية مسار نشر SEO
حولوا المجموعة غير المتسقة إلى فحص فاشل حتمي يبين علاقات المصدر والوجهة الناقصة بدقة.
الأسئلة الشائعة
متى تكون مجموعة hreflang متسقة؟
يجب أن يعلن كل URL ممثل جميع عناوين المجموعة، بما فيها نفسه. لا تكون النتيجة صحيحة إلا عند وجود كل هذه العلاقات.
هل تجلب الأداة الصفحات؟
لا. فهي تقارن التعيينات المقدمة فقط، ولا تتحقق من حالة HTTP أو الوسوم المعيارية أو محتوى الصفحة.
كيف تكتشف صفحات المصدر المفقودة؟
تُبنى المجموعة المتوقعة من عناوين المصدر والوجهة معًا؛ لذلك يُبلغ عن العنوان الذي يظهر كوجهة فقط بوصفه صفحة بلا إعلانات.
هل تعد الإعلانات المكررة تعارضات؟
لا تغير الاكتمال. تقارن الوجهات كمجموعة، بينما يظل عدد التعيينات شاملًا لكل السجلات المرسلة.
هل توحد الأداة صيغ URL المختلفة؟
لا. تجري المقارنة بدقة بعد حذف المسافات الخارجية. وحدوا المخطط والمضيف والمسار والشرطة النهائية قبل الإرسال.
ما تكلفة طلب API؟
يستخدم كل طلب السعر الأساسي المنشور البالغ $0.002. ولا تستعمل المقارنة الشبكة أو النماذج.
للمطوّرين — الوصول عبر API
كل ما في هذه الصفحة متاح برمجيًا. هذا القسم موجّه للفرق التقنية التي تريد ربط الأداة بأنظمتها الخاصة؛ بقية المستخدمين يمكنهم استخدام الأداة أعلاه مباشرة دون الحاجة لقراءة ما يلي.
الـEndpoint
صادِق على طلبك بترويسة Bearer، وأرسل طلب POST واحدًا لتدخل مهمتك قائمة التنفيذ فورًا؛ ثم تستلم النتيجة عبر webhook أو رابط موقّع.
استدعِ الخدمة من بيئتك
curl -X POST https://api.kit.forhosting.com/seo/hreflang-conflict-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}'const res = await fetch("https://api.kit.forhosting.com/seo/hreflang-conflict-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/seo/hreflang-conflict-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/seo/hreflang-conflict-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"mappings":[{"page_url":"https://example.com/en","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/en","language":"fr","target_url":"https://example.com/fr"},{"page_url":"https://example.com/fr","language":"en","target_url":"https://example.com/en"},{"page_url":"https://example.com/fr","language":"fr","target_url":"https://example.com/fr"}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/seo/hreflang-conflict-check", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)مثال على الطلب
{
"mappings": [
{
"page_url": "https://example.com/en",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/en",
"language": "fr",
"target_url": "https://example.com/fr"
},
{
"page_url": "https://example.com/fr",
"language": "en",
"target_url": "https://example.com/en"
},
{
"page_url": "https://example.com/fr",
"language": "fr",
"target_url": "https://example.com/fr"
}
]
}مثال على الاستجابة
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "seo.hreflang_conflict_check",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}الواجهة غير متزامنة: تستلم task_id فور الإرسال، ويمكنك الاستعلام عن الحالة بمعدل طلب واحد في الثانية.
الأسعار
السعر معلن كما تراه: لا tokens ولا نظام نقاط؛ وإن فشلت المهمة فلن تُحاسَب عليها.
الأخطاء
| HTTP | الرمز | المعنى |
|---|---|---|
401 | unauthorized | مفتاح الوصول مفقود أو غير صالح؛ تحقق من ترويسة Bearer في طلبك. |
402 | insufficient_balance | رصيدك لا يكفي لتنفيذ هذه المهمة؛ أعد شحن الرصيد ثم أعد المحاولة. |
404 | unknown_type | نوع المهمة المطلوب غير موجود في الكتالوج — راجع الاسم المرسل في الطلب. |
429 | rate_limited | تجاوزت الحد المسموح من الطلبات؛ انتظر قليلًا ثم أعد المحاولة. |