مقالات

راهنمای کامل پیاده‌سازی داینامیک اسکیمای Product در CMS اختصاصی

H1:راهنمای کامل پیاده‌سازی داینامیک اسکیمای Product در CMS اختصاصی

تا حالا شده به یه سایت فروشگاهی با CMS اختصاصی نگاه کنی و با خودت بگی: «اینا چطوری اسکیمای محصول رو پیاده کردن؟» وقتی افزونه‌ی یواست (Yoast) یا رنک‌مث (Rank Math) در کار نیست، همه‌چیز ترسناک به نظر می‌رسه!

من هم دقیقاً همین حس رو داشتم. کار با CMS اختصاصی مثل یه سفر ماجراجویانه به یه جنگل ناشناخته‌ست؛ تو ابزارهای آماده‌ی شهری رو نداری و باید خودت مسیر رو بسازی. اما خبر خوب اینه که این مسیر سخت، یه پاداش بزرگ داره: کنترل کامل و نتایج شگفت‌انگیز.

پیاده‌سازی داده‌های ساختاریافته (Structured Data) در وردپرس مثل یه دستور آشپزی آماده‌ست، اما در CMS اختصاصی، تو خود «سرآشپز» هستی. داری یه غذای منحصر به فرد خلق می‌کنی.

اینجا قرار نیست یه تئوری خشک رو بررسی کنیم. قراره با هم، گام به گام و بر اساس تجربه‌ی واقعی، یاد بگیریم چطور یه اسکیمای محصول داینامیک و بی‌نقص رو در دل هر CMS اختصاصی تزریق کنیم. آماده‌ای؟

جدول کاربردی: نقشه راه ۵ مرحله‌ای اسکیمای محصول در CMS اختصاصی

قبل از اینکه وارد جزئیات فنی بشیم، این نقشه راه رو ببین. این جدول بهت می‌گه هر گام برای چی حیاتیه:

گام عنوان مرحله چرا این گام حیاتی است؟ (اهمیت کلیدی)
گام اول ساخت قالب پایه (Template) ایجاد «اسکلت» و شناسنامه‌ی اصلی محصول (@type: Product).
گام دوم تزریق داینامیک در قالب «زنده کردن» اسکلت با اتصال به متغیرهای دیتابیس (مثل نام و عکس).
گام سوم پیاده‌سازی offers (قیمت و موجودی) «قلب تجاری» اسکیما؛ اثبات قابلیت فروش و ساخت اعتماد (Trust).
گام چهارم افزودن aggregateRating و reviews مُهر تأیید اجتماعی؛ نمایش «تجربه» (Experience) واقعی کاربران.
گام پنجم افزودن شناسه‌های جهانی (GTIN/MPN) «پاسپورت» محصول؛ اثبات اعتبار (Authority) جهانی و رسمی کالا.

چرا پیاده‌سازی در CMS اختصاصی یک چالش منحصربه‌فرد است؟ (فراتر از پلاگین)

بذار یه تجربه‌ی واقعی بهت بگم. کار کردن با وردپرس و افزونه‌هایی مثل یواست (Yoast) یا رنک‌مث (Rank Math) مثل اینه که یه پکیج آماده‌ی آشپزی داشته باشی. همه‌چی اندازه‌گیری شده، فقط باید ترکیبشون کنی. اما وقتی سراغ یه CMS اختصاصی (Custom CMS) می‌ری، انگار وارد آشپزخونه‌ی یه سرآشپز حرفه‌ای شدی که هیچ بسته‌بندی آماده‌ای اونجا نیست!

اینجا دیگه خبری از “نصب افزونه” و “تنظیمات ساده” نیست. تو و تیم فنی‌ات باید آستین‌ها رو بالا بزنید و همه‌چیز رو از صفر، با دست‌های خودتون بسازید. این یه چالش کاملاً متفاوته، چون دیگه «آسانسور» نداری و باید از پله‌ها بری. این فرآیند دقیقاً نقطه‌ی مقابل تولید محتوای سهل‌انگارانه یا عجولانه‌ست؛ اینجا به توجه و مراقبت واقعی برای پیاده‌سازی جزئیات نیاز داری.

تعریف چالش: عدم دسترسی به افزونه‌ها و نیاز به تزریق مستقیم کد

ببین، چالش دقیقاً اینجاست: تو اون دکمه‌ی جادویی “فعال‌سازی اسکیما” رو نداری. در CMS اختصاصی، ما باید کد اسکیما (معمولاً به‌صورت JSON-LD) رو مستقیماً در قالب (Template) صفحه تزریق (Inject) کنیم.

این یعنی:

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

مزیت کلیدی: کنترل ۱۰۰٪ بر خروجی JSON-LD و بهینه‌سازی پیشرفته

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

افزونه‌ها اغلب کدهای اضافه (Bloat) تولید می‌کنن یا دستت رو برای پیاده‌سازی‌های خلاقانه می‌بندن. اما در CMS اختصاصی، تو دقیقاً همون کدی رو می‌نویسی که گوگل بهش نیاز داره. این یعنی می‌تونی:

  • اسکیماهای تودرتو (Nested Schema) بسیار پیشرفته طراحی کنی.
  • مطمئن بشی هیچ اطلاعات اضافه‌ای وجود نداره.
  • ارزش افزوده‌ی قابل توجهی نسبت به رقبایی که فقط از پلاگین استفاده می‌کنن، ایجاد کنی. تو دیگه فقط داری یه چیز رو خلاصه نمی‌کنی، بلکه داری یه ساختار اطلاعاتی یونیک و عمیق می‌سازی.

پیش‌نیاز حیاتی: دسترسی به متغیرهای قالب (Template Variables) محصول

خب، رسیدیم به نقطه‌ی کلیدی. همه‌ی اینا یه «اگر» بزرگ داره. این روش فقط زمانی کار می‌کنه که تیم فنی بتونه متغیرهای قالب (Template Variables) رو در اختیارت قرار بده.

بذار ساده بگم: تو نمی‌تونی برای تک‌تک محصولاتت دستی کد JSON-LD بنویسی! تو باید یه قالب اسکیما بسازی و جاهای خالی رو با متغیرها پر کنی.

مثلاً:

  • "name": "{{ product_name }}"
  • "price": "{{ product_price }}"
  • "availability": "{{ product_stock_status }}"

بدون دسترسی به این متغیرها، کل پروژه شکست می‌خوره. این متغیرها همون اطلاعات اصلی و شواهدی هستن که تخصص تو رو در استفاده واقعی از اون محصول نشون می‌دن و باید به‌شکل ساختاریافته به گوگل ارائه بشن. این اطلاعات باید کامل و جامع باشن و هیچ خطای واضحی نداشته باشن.

گام اول: ساخت قالب (Template) پایه JSON-LD برای اسکیمای Product

اینجا جاییه که ما «اسکلت» کار رو می‌سازیم. یه قالب تمیز و استاندارد که قراره برای همه‌ی محصولاتمون استفاده بشه. فکر کن داری یه شناسنامه‌ی خام طراحی می‌کنی که بعداً قراره با اطلاعات واقعی پر بشه. هدف ما در این مرحله، ایجاد یه ساختار کامل و جامع بر اساس اطلاعات اصلی محصوله، دقیقاً همون چیزی که برای نشون دادن تخصص ما در مورد اون محصول لازمه.

(کد نمونه) ساختار اسکریپت پایه با @type: “Product”

اول از همه، باید به گوگل بگیم داریم در مورد چی حرف می‌زنیم. این کار رو با یه تگ <script> و تعریف @type به‌سادگی انجام می‌دیم.

این بیسِ کار ماست:

JSON
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "{{ product_name }}",
  "image": "{{ product_image_url }}",
  "description": "{{ product_short_description }}",
  "sku": "{{ product_sku }}",
  "brand": {
    "@type": "Brand",
    "name": "{{ product_brand_name }}"
  }
}
</script>

دیدی؟ ساده‌ست. ما فقط یه چارچوب ساختیم و جاهای خالی ({{ ... }}) رو گذاشتیم تا بعداً سیستم CMS به‌طور خودکار با متغیرهای قالب پرش کنه.

فیلدهای الزامی که باید به صورت داینامیک پر شوند: name و image

ببین، بعضی چیزا «باید» باشن. گوگل می‌گه اگه می‌خوای محصولت رو بشناسم، حداقل اسم و تصویرش رو بهم بگو.

  • name (نام): این هویت محصول توئه. بدون اسم، محصول وجود خارجی نداره. این متغیر باید دقیقاً «نام محصول» رو از دیتابیس بخونه.
  • image (تصویر): این ویترین محصول تو در نتایج جستجوئه. گوگل به‌شدت روی تصاویر باکیفیت و مرتبط تأکید داره. اینجا باید آدرس URL اصلی و باکیفیت‌ترین تصویر محصول قرار بگیره.

این دو تا ستون‌های اصلی ساختمون اسکیمای ما هستن. اگه اینا نباشن، کل ساختار بی‌معنی می‌شه و گوگل اصلاً اون رو به‌عنوان یه «محصول» معتبر نمی‌شناسه.

فیلدهای توصیه‌شده برای شروع: description، sku و brand

خب، بعد از اینکه اسکلت اصلی رو با name و image سر پا کردیم، وقتشه یه کم بهش جزئیات بدیم تا قوی‌تر بشه. این فیلدها به گوگل کمک می‌کنن اعتماد بیشتری به صفحه‌ی تو بکنه و ارزش افزوده‌ی واقعی رو درک کنه:

  • description (توضیحات): یه خلاصه‌ی جذاب و مفید از محصول. معمولاً همون توضیحات کوتاهِ محصول (یا خلاصه‌ی متا دیسکریپشن) رو اینجا می‌ذاریم. این به گوگل کمک می‌کنه موضوع رو سریع‌تر درک کنه.
  • sku (شناسه محصول): این کد، شناسه‌ی منحصربه‌فرد محصول تو در انبارته. وارد کردن SKU به گوگل نشون می‌ده که تو یه فروشنده‌ی واقعی و سازمان‌یافته هستی و این یه محصول واقعیه، نه یه صفحه‌ی الکی. این دقیقاً مصداق ارائه‌ی شواهد و تخصص در اون حوزه است.
  • brand (برند): این فیلد فوق‌العاده برای E-E-A-T (اعتبار و تخصص) مهمه. با معرفی برند، تو داری به گوگل «موجودیت» (Entity) برند رو متصل می‌کنی و اعتبار صفحه‌ات رو بالا می‌بری.

با همین چند تا فیلد ساده، ما یه قالب اولیه‌ی خیلی قوی ساختیم که همه‌ی اطلاعات اصلی و ضروری رو داره و هیچ خطای واضحی هم توش نیست.

گام دوم: استراتژی تزریق داینامیک در قالب صفحه محصول (Product Template)

اینجا قراره اون اسکلت JSON-LD رو برداریم و به سیستم بگیم جاهای خالی رو با اطلاعات «واقعی» هر محصول پر کنه. ما دیگه نمی‌خوایم یه کد ثابت داشته باشیم؛ می‌خوایم یه قالب هوشمند بسازیم که خودش رو با هر محصول تطبیق بده. این یعنی حرکت از یه محتوای ایستا به یه ساختار اطلاعاتی پویا و مفید.

شناسایی متغیرهای دیتابیس در CMS اختصاصی شما (مثال: {$product_title}، {{product.image_url}})

اولین و مهم‌ترین قدم، یه گپ دوستانه با تیم فنی یا برنامه‌نویس CMS اختصاصی شماست. ما باید زبان مشترک CMS رو یاد بگیریم. هر CMS متغیرهاش رو با یه فرمت خاص صدا می‌زنه.

  • بعضی‌ها (مثل سیستم‌هایی که از Smarty استفاده می‌کنن) ممکنه این شکلی باشن: {$product_title}
  • بعضی دیگه (مثل اونایی که از Twig یا Jinja2 استفاده می‌کنن) این شکلی‌ان: {{ product.name }} یا {{ product.image_url }}
  • توی یه سیستم PHP خالص هم ممکنه این شکلی باشه: <?php echo $product->name; ?>

تو باید یه لیست از این متغیرها برای اطلاعات کلیدی محصول (اسم، عکس، قیمت، SKU، برند و…) از تیم فنی بگیری. این متغیرها حکم «کلید» رو دارن که درِ دیتابیس رو برای ما باز می‌کنن تا اطلاعات اصلی رو بکشیم بیرون.

(آموزش گام به گام) فراخوانی متغیرهای بک‌اند در تگ <script>

خب، حالا که کلیدها رو داریم، وقتشه قفل‌ها رو باز کنیم. یادتونه اون قالب خام رو داشتیم؟

قالب خام ما (از گام قبل):

JSON
{
  "@type": "Product",
  "name": "{{ product_name }}",
  "image": "{{ product_image_url }}",
  "sku": "{{ product_sku }}"
}

حالا فرض کنیم برنامه‌نویس به ما گفته که متغیرها در CMS شما این‌ها هستن:

  • {$Title} برای نام محصول
  • {$MainImageAddress} برای آدرس تصویر
  • {$ProductCode} برای SKU

قالب داینامیک نهایی ما این شکلی می‌شه:

JSON
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "{$Title}",
  "image": "{$MainImageAddress}",
  "sku": "{$ProductCode}"
}
</script>

به همین سادگی! حالا وقتی صفحه‌ی محصول «الف» باز می‌شه، CMS شما خودکار {$Title} رو با «کفش نایکی مدل X» پر می‌کنه و وقتی صفحه‌ی «ب» باز می‌شه، با «گوشی سامسونگ S23» پرش می‌کنه.

محل دقیق تزریق: قرار دادن اسکریپت نهایی در بخش <head> فایل قالب محصول

این یه سؤال پرتکراره: «این کد رو کجای صفحه بذارم؟»

بهترین و تمیزترین جا، داخل تگ <head> در فایل قالب (template file) اصلی صفحه‌ی محصول شماست. (مثلاً product-template.tpl یا product.html یا هر اسمی که داره).

چرا <head>؟

چون <head> محل اعلام اطلاعات «فراداده» (Metadata) به ربات‌هاست. گوگل (و بقیه موتورهای جستجو) اول به <head> نگاه می‌کنن تا بفهمن کلیت صفحه در مورد چیه. وقتی اسکیمای JSON-LD رو اونجا می‌ذاری، داری خیلی شیک و سازمان‌یافته به گوگل می‌گی: «سلام! قبل از اینکه درگیر خوندن کل محتوای <body> بشی، بذار بهت بگم این صفحه یه ‘محصول’ هست و اینم شناسنامه‌شه.» این کار تخصص و نظم شما رو نشون می‌ده.

(تجربه عملی) استفاده از توابع PHP/Python/Node.js برای “Escape” کردن متون (جلوگیری از شکستن JSON)

بذار یه تجربه‌ی تلخ ولی خیلی رایج رو بهت بگم. فرض کن همه‌ی این کارها رو کردی، اما یهو می‌بینی اسکیما برای بعضی محصولات کار نمی‌کنه و تو گوگل ارور (Error) می‌ده. چرا؟

چون اسم محصول این بوده: تی‌شرت مردانه "کلاسیک"

اون علامت کوتیشن (") که داخل اسم محصوله، ساختار JSON تو رو می‌شکنه! چون JSON فکر می‌کنه اونجا انتهای فیلد name هست.

راه‌حل چیه؟ “Escape” کردن.

ما باید به سرور بگیم که قبل از گذاشتن متن داخل JSON، کاراکترهای دردسرساز (مثل ” یا \ یا خط جدید) رو خنثی کنه (Escape کنه).

  • در PHP: امن‌ترین راه اینه که کل داده‌ها رو اول در یک آرایه PHP بسازی و در نهایت از json_encode() استفاده کنی. این تابع خودکار همه‌چیز رو Escape می‌کنه. اگه مجبوری مستقیم متغیر رو بذاری، می‌تونی از توابعی مثل addslashes() یا htmlspecialchars() (با تنظیمات خاص) استفاده کنی.
  • در Python (مثلاً با Jinja2/Django): می‌تونی از فیلتر |tojson (اگه کتابخونه‌اش باشه) یا |escapejs استفاده کنی.
  • در Node.js: معمولاً تو خود کنترلر، آبجکت رو می‌سازی و با JSON.stringify() تبدیلش می‌کنی و به قالب پاس می‌دی که امن‌ترین راهه.

این مرحله‌ی آخر شاید کمی فنی به نظر برسه، اما دقیقاً همون ارزش افزوده‌ای هست که تو رو از یه کارشناس محتوای معمولی به یه متخصص فنی تبدیل می‌کنه. این یعنی تو فقط محتوا نمی‌سازی، بلکه مطمئن می‌شی که محتوات بدون هیچ خطای واضحی و به بهترین شکل به ربات‌ها ارائه می‌شه.

خب، رسیدیم به جایی که می‌تونم بگم «قلب تپنده‌ی» اسکیمای محصوله. جدی می‌گم.

اگه گام‌های قبلی ساختن «ظاهر» و «هویت» محصول بودن (که چی هست و چه شکلیه)، این گام، یعنی offers، «روح» تجاری و واقعی رو بهش می‌ده. این دقیقاً همون نقطه‌ایه که اعتماد (Trust) ساخته می‌شه و گوگل می‌فهمه تو یه ویترین قشنگ نیستی، بلکه یه مغازه‌ی واقعی با کالای قابل خریدی.

گام سوم (حیاتی): پیاده‌سازی داینامیک موجودیت offers (قیمت و موجودی)

فکر کن وارد یه فروشگاه خیلی شیک شدی، محصول رو برمی‌داری، ولی هیچ اتیکت قیمتی روش نیست. هرچقدر هم ویترین خوشگل باشه، تو نمی‌تونی «تصمیم» بگیری. بخش offers همون اتیکت قیمته. این بخش به گوگل می‌گه «این محصول چنده و آیا اصلاً می‌تونی بخریش؟».

چرا offers الزامی است؟ (بدون آن اسکیما ناقص است)

ببین، گوگل می‌خواد به کاربرش «مفیدترین» نتیجه رو نشون بده. (این دقیقاً برمی‌گرده به همون اصل «محتوای مفید» که قبلاً در موردش صحبت کردیم).

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

گوگل صراحتاً می‌گه برای اینکه بتونی ریچ اسنیپت‌های محصول (مثل نمایش قیمت، ستاره‌ها و وضعیت موجودی در نتایج جستجو) رو بگیری، باید offers رو داشته باشی. بدون اون، اسکیمای تو از نظر گوگل یه اسکیمای محصول «کامل» و «قابل اعتماد» برای فروش نیست. تو داری شواهد کلیدی فروش رو ازش پنهون می‌کنی، و این یعنی از دست دادن اعتبار.

(کد نمونه) ساختار تودرتوی (Nested) offers با @type: “Offer”

ما offers رو به‌عنوان یه موجودیت «تودرتو» (Nested) داخل همون اسکیمای Product که قبلاً ساختیم، جا می‌دیم. اینجوری گوگل می‌فهمه این «پیشنهاد فروش» دقیقاً متعلق به همین محصوله.

نگاه کن چطور تمیز داخل ساختار قبلی می‌شینه:

JSON
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "{$Title}",
  "image": "{$MainImageAddress}",
  "description": "{$ShortDescription}",
  "sku": "{$ProductCode}",
  "brand": {
    "@type": "Brand",
    "name": "{$BrandName}"
  },

  // بخش حیاتی جدید اینجاست
  "offers": {
    "@type": "Offer",
    "price": "{$ProductPrice}",
    "priceCurrency": "IRR",
    "availability": "https://schema.org/InStock", // این داینامیک می‌شه
    "url": "{$ProductCanonicalUrl}" // آدرس همین صفحه
  }
}
</script>

فراخوانی داینامیک price و priceCurrency (مثال: “IRR” یا “USD”)

اینجا دو تا متغیر کلیدی داریم که باید از دیتابیس بیان:

  1. price (قیمت): این باید متغیر قیمت نهایی محصول شما باشه (مثلاً {$ProductPrice}). نکته‌ی مهم: این باید عدد خالص باشه که توی دیتابیس ذخیره شده (مثلاً 1500000). حواست باشه که نباید کاراکترهایی مثل «تومان» یا «,» (کاما) اینجا باشه. ما معمولاً این رو به‌صورت رشته (String) داخل کوتیشن می‌ذاریم تا مطمئن باشیم JSON به هم نمی‌ریزه.
  2. priceCurrency (واحد پول): این برای E-E-A-T حیاتیه! به گوگل می‌گه واحد پولت چیه و نشون می‌ده تو یه کسب‌وکار معتبر با واحد پول مشخصی.
    • برای ما در ایران، این مقدار باید IRR باشه (ریال ایران طبق استاندارد ISO 4217).
    • اگه سایتت دلاریه، می‌ذاری USD.
    • این فیلد رو معمولاً دستی (Hardcode) می‌نویسیم، چون واحد پول سایت ثابته و از دیتابیس نمیاد.

نحوه مدیریت داینامیک availability (موجودی) بر اساس دیتابیس

این بخش مورد علاقه‌ی منه! اینجاست که تو «تجربه‌ی» (Experience) واقعی کاربر رو شکل می‌دی. هیچ‌چیز بدتر از این نیست که کاربر روی لینک تو کلیک کنه و ببینه محصول ناموجوده. ما باید این رو صادقانه و داینامیک به گوگل بگیم.

ما نمی‌تونیم اینو دستی بنویسیم InStock (موجود). چی می‌شه اگه محصول فردا تموم بشه؟ ما باید یه «شرط» (Condition) توی کدمون بذاریم که از دیتابیس بپرسه: «این محصول موجوده یا نه؟»

(کد نمونه) پیاده‌سازی شرطی: InStock در مقابل OutOfStock

اینجا جاییه که دوباره به تیم فنی و زبان برنامه‌نویسی CMS تون نیاز داریم. ما باید یه منطق شرطی شبیه به این رو توی قالبمون پیاده کنیم.

(این یه مثال با سینتکس شبیه به Twig/Jinja2 هست که در خیلی از CMSها استفاده می‌شه):

JSON
  "offers": {
    "@type": "Offer",
    "price": "{{ product.price }}",
    "priceCurrency": "IRR",
    
    // این همون منطق شرطی داینامیک هست
    {% if product.stock > 0 %}
      "availability": "https://schema.org/InStock"
    {% else %}
      "availability": "https://schema.org/OutOfStock"
    {% endif %}
  }

با این کد، اگه موجودی محصول در دیتابیس صفر باشه، اسکیما خودکار می‌گه OutOfStock (ناموجود). این یعنی اعتماد! تو داری اطلاعات دقیق و به‌روز می‌دی و گوگل عاشق این دقته.

مدیریت محصولات متغیر (Variable Products): پیاده‌سازی آرایه‌ای از offers

خب، حالا اون چالش واقعی: اگه محصولت متغیر باشه چی؟ مثلاً یه تی‌شرت که هم آبی داره، هم قرمز؛ هم سایز L، هم M. قیمت‌هاشون هم شاید با هم فرق کنه.

اینجا دیگه یه Offer ساده جواب نمی‌ده.

راه‌حل اینه که offers رو به‌جای یه آبجکت {}، تبدیل به یه «آرایه» (Array) [ ] کنیم. یعنی لیستی از همه‌ی Offerهای ممکن.

JSON
"offers": [
  {
    "@type": "Offer",
    "name": "تی‌شرت قرمز - سایز L", // مهمه که هر آفر رو مشخص کنیم
    "price": "350000",
    "priceCurrency": "IRR",
    "availability": "https://schema.org/InStock",
    "sku": "TSHIRT-RED-L"
  },
  {
    "@type": "Offer",
    "name": "تی‌شرت آبی - سایز M",
    "price": "340000",
    "priceCurrency": "IRR",
    "availability": "https://schema.org/OutOfStock",
    "sku": "TSHIRT-BLUE-M"
  }
  // و الی آخر...
]

اینجا دیگه اوج تخصص و پیاده‌سازی دقیق فنیه. ما باید با یه حلقه‌ی for توی قالبمون، به ازای هر متغیر (variation) محصول، یه آبجکت Offer جداگونه توی اون آرایه بسازیم. این کار سخته، اما پوشش جامع و کاملی از محصول به گوگل می‌ده.

پیاده‌سازی offers شاید فنی‌ترین بخش کار باشه، اما دقیقاً همون چیزیه که تفاوت رو بین یه صفحه‌ی «اطلاعاتی» و یه صفحه‌ی «تجاری» قابل اعتماد ایجاد می‌کنه.

خب، رسیدیم به گام چهارم که به نظر من، قلب تپنده‌ی E-E-A-T (تجربه، تخصص، اعتبار، اعتماد) در اسکیمای محصوله.

تا الان ما داشتیم به گوگل می‌گفتیم محصولمون چیه و چنده. حالا وقتشه بذاریم مشتری‌هامون حرف بزنن و اعتبار ما رو تأیید کنن. این همون «مُهر تأیید اجتماعی» (Social Proof) هست که گوگل براش می‌میره!

گام چهارم (تقویت E-E-A-T): افزودن aggregateRating و reviews

اینجا داریم شواهد و تجربه‌ی (Experience) واقعی کاربرهای قبلی رو به گوگل نشون می‌دیم. داریم می‌گیم: «ببین، من تنها کسی نیستم که می‌گم این محصول عالیه. ۱۵۰ نفر دیگه هم همینو می‌گن و میانگین امتیاز ما ۴.۷ هست.» این یعنی ساختن اعتماد (Trust) خالص.

(کد نمونه) ساختار تودرتوی aggregateRating (شامل ratingValue و reviewCount)

اول از همه، خلاصه‌ی امتیازها رو اضافه می‌کنیم. aggregateRating یه آبجکت تودرتوی دیگه است که داخل همون اسکیمای Product (در کنار offers و brand) قرار می‌گیره.

این کد، یه خلاصه‌ی مدیریتی به گوگل می‌ده:

JSON
<script type="application/ld+json">
{
  // ... (تمام کدهای قبلی مثل name, offers و ...)

  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "{$AverageRating}", // مثلا: "4.7"
    "reviewCount": "{$TotalReviews}"   // مثلا: "145"
  }
  
  // ... (ادامه اسکیما اگه چیزی مونده)
}
</script>

این کد به گوگل می‌گه: «از مجموع ۱۴۵ نقد، میانگین امتیاز این محصول ۴.۷ است.»

چگونه متغیرهای میانگین امتیاز و تعداد نظرات را از دیتابیس فراخوانی کنیم؟

اینجا دقیقاً مثل همون کاریه که برای قیمت و موجودی کردیم. ما نمی‌تونیم این اعداد رو دستی وارد کنیم! چون هر روز داره نظر جدید ثبت می‌شه و این اعداد باید «واقعی» و «به‌روز» باشن.

دوباره باید با تیم فنی صحبت کنی و این دو تا متغیر حیاتی رو ازشون بخوای:

  1. {$AverageRating} (یا هر اسم دیگه‌ای): متغیری که میانگین امتیازات ثبت‌شده برای اون محصول خاص رو نگه می‌داره (مثلاً 4.72).
  2. {$TotalReviews} (یا مشابهش): متغیری که تعداد کل نظرات تأییدشده‌ی اون محصول رو می‌شماره (مثلاً 145).

سیستم CMS شما باید بتونه در لحظه‌ی لود شدن صفحه، این دو تا عدد رو از دیتابیس محاسبه کنه و در اختیار ما بذاره تا در قالب JSON-LD تزریق کنیم. این کار تخصص شما رو در ارائه‌ی داده‌ی دقیق نشون می‌ده.

(اختیاری اما قدرتمند) تزریق داینامیک ۱-۳ نظر برتر در اسکیمای Review

خب، اگه aggregateRating خلاصه‌ی آمار بود، review خودِ «محتوای مفید» و «تجربه‌ی» دست‌اوله. این بخش دیگه اختیاری نیست، به نظر من یه حرکت فوق‌العاده هوشمندانه برای اعتبار سازیه.

ما می‌تونیم به گوگل بگیم: «اون ۱۴۵ تا نظر الکی نبودن، بیا اینم ۳ تا از بهترین‌هاشون که ببینی واقعاً چی گفتن.»

ما این کار رو با اضافه کردن یه «آرایه» (Array) به اسم review انجام می‌دیم.

(کد نمونه) ساختار Review (شامل author, datePublished, reviewRating)

این آرایه‌ی review هم درست مثل aggregateRating، مستقیماً داخل اسکیمای Product می‌شینه.

JSON
<script type="application/ld+json">
{
  // ... (کدهای name, offers, aggregateRating و ...)

  "review": [
    // نظر اول (این باید با یه حلقه For داینامیک پر بشه)
    {
      "@type": "Review",
      "author": {
        "@type": "Person",
        "name": "{$Review1_AuthorName}" // مثلا: "نگین شیخ الاسلامی"
      },
      "datePublished": "{$Review1_Date}", // مثلا: "2024-10-28"
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "{$Review1_Rating}", // مثلا: "5"
        "bestRating": "5" // سقف امتیاز رو مشخص می‌کنیم
      },
      "description": "{$Review1_Text}" // متن خود نظر
    },
    // نظر دوم
    {
      "@type": "Review",
      "author": {
        "@type": "Person",
        "name": "{$Review2_AuthorName}" 
      },
      // ... (بقیه فیلدهای نظر دوم)
    }
    // ... و الی آخر
  ]
}
</script>

نکته‌ی فنی: تیم فنی شما باید یه کوئری به دیتابیس بزنه، مثلاً «۳ نظر برتر (۵ ستاره) این محصول که جدیدتر هستن رو انتخاب کن» و بعد با یه حلقه (for loop) در قالب، این آرایه‌ی review رو به‌صورت داینامیک بسازه.

این کار یعنی شما ارزش افزوده‌ی فوق‌العاده‌ای ایجاد کردی. تو فقط ادعا نکردی، بلکه شواهد کامل و جامع رو مستقیماً در اختیار گوگل گذاشتی تا تجربه‌ی کاربرانت رو ببینه.

گام پنجم (اعتماد): افزودن شناسه‌های جهانی محصول

فکر کن می‌خوای از مرز رد بشی. تو می‌تونی بگی «من نگین هستم»، اما تا وقتی پاسپورتت رو نشون ندی، حرفت فقط یه «ادعا»ست. شناسه‌های جهانی محصول (GTIN, MPN) دقیقاً حکم همون پاسپورت رو برای محصول تو دارن.

این شناسه‌ها به گوگل ثابت می‌کنن که محصول تو یه موجودیت واقعی، شناخته‌شده و قابل ردیابی در سطح جهانیه. این کار، ارائه‌ی شواهد و اطلاعات اصلی به شفاف‌ترین شکل ممکنه و اعتبار (Authority) تو رو به‌عنوان یه فروشنده‌ی متخصص به‌شدت بالا می‌بره.

اهمیت gtin (بارکد)، mpn و sku در اعتبارسنجی محصول توسط گوگل

بیا این سه تا رو از هم باز کنیم تا دقیقاً بفهمیم چرا هرکدوم مهم هستن:

  • sku (Stock Keeping Unit): این شناسه‌ی داخلی تو هست. (قبلاً هم در موردش حرف زدیم). این به گوگل می‌گه تو یه فروشگاه سازمان‌یافته با سیستم انبارداری مشخصی. این نشونه‌ی تخصص و نظم داخلی توئه.
  • mpn (Manufacturer Part Number): این شماره‌ی قطعه‌ایه که کارخونه‌ی سازنده به محصول داده. این به گوگل کمک می‌کنه تا محصول تو رو با همین محصول در سایت‌های دیگه (مثلاً سایت اصلی سازنده) مطابقت بده.
  • gtin (Global Trade Item Number): این شاه‌کلیده! این همون بارکد جهانی محصوله (مثل EAN یا UPC). وقتی تو gtin رو ارائه می‌دی، داری به گوگل می‌گی: «ببین، محصول من این‌قدر معتبره که یه کد جهانی یکتا داره.» این قوی‌ترین سیگنال برای گوگل برای اتصال «موجودیت» (Entity) صفحه‌ی تو به «موجودیت» جهانی اون کالا در گراف دانش گوگله.

(کد نمونه) نحوه افزودن داینامیک این شناسه‌ها به قالب JSON-LD

اضافه کردنشون خیلی ساده‌ست. این‌ها فیلدهای مستقیمی هستن که داخل همون آبجکت اصلی Product قرار می‌گیرن.

JSON
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "{$Title}",
  
  // ... (همه کدهای قبلی مثل offers, aggregateRating و ...)

  // بخش شناسه‌های جهانی
  "sku": "{$ProductCode}",
  "mpn": "{$ManufacturerPartNumber}",
  "gtin13": "{$BarcodeEAN}" // یا gtin14, gtin8, gtin بستگی به نوع بارکدتون داره

  // ... (بخش brand که الان می‌گیم)
}
</script>

نکته‌ی حیاتی: این شناسه‌ها (مخصوصاً mpn و gtin) ممکنه برای همه‌ی محصولاتت وجود نداشته باشن (مثلاً محصولات دست‌ساز). تو باید از تیم فنی بخوای که این فیلدها رو به‌صورت شرطی تزریق کنن. یعنی: «فقط اگر فیلد GTIN در دیتابیس برای این محصول پر شده بود، این خط رو به JSON اضافه کن.» این کار جلوی ایجاد خطای الکی رو می‌گیره.

پیاده‌سازی داینامیک brand با @type: “Brand” یا “Organization”

ما قبلاً هم به brand اشاره کردیم، اما اینجا جاشه که کاملش کنیم، چون «برند» هم یه شناسه‌ی کلیدی اعتمادسازه.

ما داریم «موجودیت» برند رو به «موجودیت» محصول وصل می‌کنیم.

  • @type: "Brand" در مقابل "Organization":
    • برای ۹۹٪ مواقع در اسکیمای محصول، استفاده از @type: "Brand" که فقط شامل name هست، کافی، تمیز و استاندارده.
    • @type: "Organization" معمولاً وقتی استفاده می‌شه که خودِ «برند» همون «سازمان» فروشنده باشه و بخوای جزئیات بیشتری مثل logo یا url خود سازمان رو هم اضافه کنی.

پیشنهاد من برای سادگی و استاندارد بودن در اسکیمای محصول، استفاده از Brand هست:

JSON
  // ... (ادامه کدهای بالا)

  "brand": {
    "@type": "Brand",
    "name": "{$BrandName}"
  }

} // انتهای اسکریپت
</script>

این کد به‌سادگی محصول رو به برندش لینک می‌کنه و اعتبار هر دو رو تقویت می‌کنه.

با تکمیل این گام، ما یه شناسنامه‌ی کامل، جامع و رسمی برای محصولمون ساختیم که پر از شواهد قابل اتکاست.

خب، ما با هم اون ماشین مسابقه (اسکیمای داینامیک) رو از صفر ساختیم. تمام قطعات فنی، موتور (Offers) و سیستم اعتماد (Ratings) رو سر جاش گذاشتیم.

حالا رسیدیم به گام نهایی. لحظه‌ی حقیقت! وقتشه سوییچ رو بچرخونیم و ببینیم این ماشین اصلاً روشن می‌شه و حرکت می‌کنه یا نه.

گام نهایی: اعتبارسنجی و عیب‌یابی (Validation) اسکیمای داینامیک

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

استفاده از ابزار Google Rich Results Test (تست یک URL محصول واقعی)

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

چطور این کار رو بکنیم؟

  1. کد نهایی رو که روی سایتت اجرا کردی (Deploy کردی).
  2. یکی از URLهای محصول واقعی سایتت رو که مطمئنی اسکیما روش تزریق شده، کپی کن.
  3. برو به Google Rich Results Test.
  4. URL رو وارد کن و تست رو اجرا کن.

دنبال چی بگردیم؟

  • تیک سبز ✅: باید ببینی که گوگل می‌گه «Page is eligible for rich results».
  • بخش “Products”: مهم‌تر از تیک سبز، اینه که زیر «Detected items»، گزینه‌ی «Products» رو ببینی. روش کلیک کن.
  • بررسی فیلدها: حالا باید تمام اون متغیرهایی که با هم ساختیم رو اینجا ببینی که پر شدن. name، price، availability (که باید InStock یا OutOfStock باشه)، reviewCount و ratingValue و اگه gtin داشتی، اون هم باید اینجا باشه.

اگه اینا رو دیدی، یعنی تبریک می‌گم! متغیرهای داینامیک تو دارن به‌درستی از دیتابیس خونده می‌شن.

اشتباهات رایج در CMS اختصاصی: متغیرهای خالی (Null) و خطای فرمت قیمت (مثال: وجود “تومان”)

بذار از تجربه‌های تلخ خودم بهت بگم تا تو تکرارشون نکنی. توی CMS اختصاصی، ما داریم مستقیم با دیتابیس حرف می‌زنیم و این یعنی ممکنه داده‌ی «کثیف» به ما برسه.

اشتباه رایج اول: متغیرهای خالی (Null)

  • سناریو: تو برای gtin یه متغیر {$Barcode} گذاشتی. حالا یه محصول داری که بارکد نداره.
  • اتفاقی که می‌افته: اون متغیر یا «خالی» (Empty String) یا بدتر از اون null برمی‌گردونه. این می‌تونه کل ساختار JSON تو رو بشکنه و گوگل کلاً اسکیمات رو نادیده بگیره.
  • راه‌حل (که قبلاً گفتیم): پیاده‌سازی شرطی. باید به تیم فنی بگی: «فقط اگه متغیر {$Barcode} مقدار داشت، اون خط "gtin": "..." رو چاپ کن.»

اشتباه رایج دوم: خطای فرمت قیمت (قاتل JSON!)

  • سناریو: متغیر قیمت ({$ProductPrice}) به‌جای عدد 1500000، این رو برمی‌گردونه: "1,500,000 تومان".
  • اتفاقی که می‌افته: JSON به هم می‌ریزه! چون price باید یه عدد خالص (یا رشته‌ی عددی) باشه. وجود کاما (,) و کلمه‌ی «تومان» باعث خطای Invalid syntax در JSON می‌شه.
  • راه‌حل: متغیری که از بک‌اند می‌گیری باید عدد خام و بدون فرمت باشه.

جلوگیری از این خطاها دقیقاً همون چیزیه که تخصص و اعتبار ما رو در پیاده‌سازی فنی نشون می‌ده.

بررسی گزارش “Products” در سرچ کنسول پس از اجرای نهایی

خب، Rich Results Test برای چک کردن لحظه‌ای و یک URL بود. اما سرچ کنسول، گزارش بلندمدت و کامل از همه‌ی URLهای ماست.

بعد از اینکه کدت رو منتشر کردی و چند روز تا چند هفته گذشت (بسته به سرعت کرال گوگل):

  1. برو به سرچ کنسول.
  2. در منوی کناری، برو پایین تا به بخش “Enhancements” (یا “Shopping” -> “Product snippets”) برسی.
  3. اینجا سه تا نمودار می‌بینی: Error (قرمز)، Valid with warnings (زرد)، Valid (سبز).
  • Error (خطاها): اینا فاجعه‌ان و باید فوراً رفع بشن. معمولاً همون خطاهای فرمتی یا فیلدهای الزامی (مثل offers یا name) هستن که جا افتادن.
  • Valid with warnings (معتبر با هشدار): این بهترین بخش برای بهینه‌سازیه! گوگل داره بهت می‌گه: «اسکیمات درسته، ولی می‌تونست بهتر باشه.» هشدارهای رایج اینجا اینان:
    • Missing field "aggregateRating" (گام چهارم رو یادت رفت!)
    • Missing field "review"
    • Missing field “gtin” (گام پنجم رو یادت رفت!)

      این هشدارها، چک‌لیست کارهای بعدی تو برای ایجاد ارزش افزوده‌ی بیشتر هستن.

  • Valid (معتبر): هدف ما اینه که همه‌ی URLهامون به اینجا برسن (حتی اگه با هشدار باشن).

خب، اینم از پایان ماراتن پیاده‌سازی اسکیمای محصول در CMS اختصاصی. یه کار فنی عمیق که مستقیماً روی E-E-A-T و اعتماد سایتت تأثیر می‌ذاره.

جمع‌بندی

خب، اینم از سفر ما برای رام کردن اسکیمای محصول در CMS اختصاصی!

دیدیم که چطور می‌شه از یه قالب خام JSON-LD شروع کرد و گام به گام، با تزریق داینامیک متغیرهای دیتابیس، یه شناسنامه‌ی کامل، زنده و پویا برای محصولمون ساخت. ما با هم offers رو برای نشون دادن قیمت و موجودی، aggregateRating و reviews رو برای اثبات «تجربه» کاربران، و در نهایت شناسه‌های جهانی مثل gtin رو برای ساختن «اعتماد» مطلق پیاده‌سازی کردیم.

آره، قبول دارم؛ این کار خیلی فنی‌تر از تیک زدن گزینه‌های یه افزونه‌ست. نیاز به همکاری نزدیک با تیم فنی داره. اما تفاوتی که ایجاد می‌کنه، زمین تا آسمونه. تو دیگه به گوگل یه «خلاصه» نمی‌دی، بلکه داری «شواهد» و «داده‌های اصلی» رو به کامل‌ترین شکل ممکن بهش نشون می‌دی و این یعنی اوج E-E-A-T.

حالا تو بگو، فکر می‌کنی بزرگترین مانع برای اجرای این ۵ گام در CMS اختصاصی خودت چیه؟ چالش فنی یا هماهنگی با تیم برنامه‌نویسی؟ خوشحال می‌شم تجربیاتت رو بشنوم.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *