البيانات المهيكلة في Next.js، مُولَّدة من رسم بياني واحد
معظم JSON-LD يُنشَر ككتل أربع منفصلة تُعيد كل واحدة إعلان المؤسسة. رسمٌ بياني واحد متّصل بمراجع @id ثابتة شيفرةٌ أقل، وهو ما يستطيع الزاحف تحليله.
البيانات المهيكلة هي الجزء من السيو التقني الذي تتّسع فيه المسافة أكثر ما
تتّسع بين ما تطلقه الفرق وما تكافئ عليه المواصفة. التنفيذ المعتاد مكوّن لكل
نوع صفحة، يبثّ كلٌّ منه <script type="application/ld+json"> خاصًّا به،
ويُعيد كلٌّ منه إعلان المؤسسة والموقع والشعار.
هذا يجتاز التحقّق. وهو يخبر الزاحف أيضًا أن موقعك يحتوي أربع مؤسّسات لا رابط بينها تتصادف في الاسم.
رسمٌ واحد، لا أربع كتل
المفتاح @graph موجود لهذا. يحوي قائمة عُقد، لكلٍّ منها @id ثابت، وتشير
العُقد بعضها إلى بعض بذلك الـ@id بدل أن تكرّر محتوى بعضها.
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "@id": "https://example.com/#org", "name": "Example" },
{ "@type": "WebSite", "@id": "https://example.com/#site", "publisher": { "@id": "https://example.com/#org" } },
{ "@type": "WebPage", "@id": "https://example.com/blog/post#page", "isPartOf": { "@id": "https://example.com/#site" } },
{ "@type": "Article", "@id": "https://example.com/blog/post#article", "mainEntityOfPage": { "@id": "https://example.com/blog/post#page" } }
]
}أربع عُقد، ومؤسسة واحدة، وكل علاقة مذكورة مرّة واحدة. قيم الـ@id هي الآلية
كلّها: هي ما يتيح للزاحف أن يدمج العقدة التي يراها هنا مع العقدة نفسها في كل
صفحة أخرى.
قاعدتان تجعلانها تعمل:
- روابط مطلقة دائمًا.
#orgوحده ليس معرّفًا، بل جزء رابط يعني شيئًا مختلفًا في كل صفحة. - ثابتة إلى الأبد. الـ
@idالذي يتغيّر بين عمليات النشر - لأنه بُني من slug عُدِّل، أو من معرّف صفّ في قاعدة بيانات - يُهدر كل ما راكمه الزاحف مقابله.
وَلِّدها بدل أن تكتبها
سبب انحراف الـJSON-LD المكتوب يدويًا أن لا شيء يجبره على موافقة الصفحة.
فيتغيّر العنوان في تصدير metadata ويحتفظ headline في البيانات المهيكلة
بالقديم، لأنهما نصّان في ملفّين.
العلاج مساعد واحد محدَّد الأنواع، يُستدعى من الموضع الذي يعرف الجواب أصلًا:
// lib/jsonld.ts
export function articleNode({ url, title, description, published, modified }: ArticleInput) {
return {
'@type': 'Article',
'@id': `${url}#article`,
headline: title,
description,
datePublished: published,
dateModified: modified ?? published,
mainEntityOfPage: { '@id': `${url}#page` },
publisher: { '@id': `${SITE}#org` },
};
}// app/blog/[slug]/page.tsx
<JsonLd data={graph(
webPageNode({ url, title: doc.title, description: doc.description }),
articleNode({ url, title: doc.title, description: doc.description,
published: doc.date, modified: doc.updated }),
breadcrumbNode(trail),
)} />الآن لا تستطيع البيانات المهيكلة أن تخالف الصفحة، لأنها تقرأ المتغيّرات نفسها التي تعرضها الصفحة. وهذا هو مبدأ الروابط المعيارية وخرائط الموقع التي لا يمكن أن تنحرف: مصدر واحد للحقيقة، يُولَّد عند الطرفين.
أين تنتمي داخل الاستجابة
في الـHTML المعروض على الخادم. أي <script> يحقنه مكوّن عميل بعد الترطيب هو
ترميز قد ينفّذه الزاحف وقد لا ينفّذه، ولا داعي للمراهنة - فالبيانات معروفة على
الخادم.
export function JsonLd({ data }: { data: object }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
);
}dangerouslySetInnerHTML هنا صحيحة وليست اختصارًا: فReact يهرّب الأبناء
النصّيين، وهو ما يُفسد الـJSON. ما يجب ألّا تفعله هو إدراج نصّ يتحكّم به
المستخدم دون تهريب < - فتعليقٌ يحوي </script> سيغلق الوسم وينفّذ ما بعده.
الأنواع التي تستحقّ، والأنواع التي مجرّد استعراض
تستحقّ البيانات المهيكلة مكانها حين تقابل نتيجة غنيّة أو تحدّد كِيانًا. وما عدا ذلك ترميزٌ لا يقرأه أحد.
تستحقّ:
OrganizationوWebSite، مرّة واحدة، ويُشار إليهما من كل مكان.BreadcrumbList، فهو يظهر مباشرة في النتائج.Articleعلى المقالات، وProductببياناتOfferحقيقية على المنتجات.FAQPage، لكن فقط حيث تكون الأسئلة ظاهرة على الصفحة. وسْم أسئلة غير معروضة مخالفة للإرشادات، لا حيلة ذكية.LocalBusinessأو أحد أنواعها الفرعية حيث يوجد عنوان حقيقي. انتبه: الأنواع الفرعية تشترطaddress- فـProfessionalServiceبلا عنوان غير صالح، وهذه طريقة شائعة لإطلاق رسمٍ معطوب مع الاعتقاد أنه أغنى.
لا تستحقّ كثيرًا:
Reviewكتبتها عن نفسك. فترميز المراجعات الذاتية غير مؤهّل للنتائج الغنيّة منذ سنوات.HowToوRecipeعلى صفحات ليست هذه ولا تلك.speakableوSiteNavigationElementوبقيّة الذيل الطويل الذي لا تستهلكه أي واجهة.
كيف تتحقّق
أداتان، وتجيبان عن سؤالين مختلفين. اختبار النتائج الغنيّة يخبرك إن كانت
الصفحة مؤهّلة لنوع نتيجة بعينه. ومدقّق ترميز Schema يخبرك إن كان رسمك سليم
البنية - وهو الذي يلتقط مرجع @id معلَّقًا في الفراغ، وهو ما تتجاهله الأداة
الأولى بلا اكتراث.
شغّل الاثنتين على الـHTML المعروض للصفحة المنشورة، لا على مقتطف ملصوق. المقتطف هو ما كتبتَه، والـHTML المعروض هو ما أطلقتَه - وفي المواقع التي أمامها طبقة تخزين مؤقّت ليسا الشيء نفسه بالضرورة.
