المشكلة مع "الودجات" (Widgets)
تعامل معظم منصات المراجعات موقع الويب الخاص بك وكأنه لوحة إعلانية لعلامتها التجارية. فهي تمنحك <iframe> جامدًا أو "ودجت" JavaScript ثقيلًا والذي يقوم بـ:
- خفض نقاط Lighthouse الخاصة بك بسبب النصوص البرمجية لجهات خارجية.
- التعارض مع نظام التصميم الخاص بك (خطوط خاطئة، ألوان غير متناسقة).
- العمل كحصان طروادة لتوجيه الزيارات والبيانات مرة أخرى إلى منصتهم، وليس منصتك.
في Reviewlee، نؤمن بأن المراجعات هي بنية تحتية. نحن نقدم قاعدة البيانات، ونماذج الجمع، ومحرك التحقق—ولكن طريقة عرض تلك البيانات يجب أن تكون قرارك أنت.
لماذا تختار "Headless"؟
باستخدام Reviewlee API ("المراجعات بدون واجهة" أو Headless Reviews)، ستحصل على:
- إزاحة تصميم صفرية (Zero Layout Shift): عرض المراجعات على الخادم (SSR/RSC) لظهور فوري.
- علامة تجارية مثالية: استخدم فئات CSS/Tailwind الخاصة بك.
- تفوق في تحسين محركات البحث (SEO): المراجعات جزء من HTML الخاص بك، وليست محقونة بواسطة JS بعد التحميل.
لنبنِ مكون مراجعة مخصصًا باستخدام Next.js 16 و Tailwind CSS.
المتطلبات الأساسية
- حساب Reviewlee (مجاني أو احترافي).
- مفتاح API العام الخاص بك (موجود في الإعدادات > API).
- مشروع Next.js (على الرغم من أن هذا يعمل مع Remix، Astro، وغيرها).
الخطوة 1: جلب المراجعات (جانب الخادم)
في Next.js App Router، نقوم بجلب البيانات مباشرة في مكون الخادم (Server Component). هذا يضمن أن محركات البحث ترى المراجعات على الفور.
// lib/api.ts
import { notFound } from "next/navigation";
export interface Review {
id: string;
rating: number;
title: string;
body: string;
author_name: string;
verified: boolean;
created_at: string;
}
export async function getReviews(formId: string) {
const res = await fetch(
`https://api.reviewlee.com/api/v1/reviews?formId=${formId}&status=published`,
{
headers: {
// استخدم مفتاحك العام إذا كنت تجلب من العميل،
// أو المفتاح السري إذا كنت تستخدم البروكسي/تجلب من الخادم.
Authorization: `Bearer ${process.env.REVIEWLEE_API_KEY}`,
},
next: { revalidate: 3600 }, // التخزين المؤقت لمدة ساعة
}
);
if (!res.ok) {
if (res.status === 404) return [];
throw new Error("فشل في جلب المراجعات");
}
const data = await res.json();
return data.reviews as Review[];
}
الخطوة 2: مكون بطاقة المراجعة
الآن، لنقم ببناء واجهة المستخدم. سنستخدم lucide-react للنجوم و Tailwind للتنسيق.
// components/review-card.tsx
import { Star, CheckCircle2 } from "lucide-react";
import { cn } from "@/lib/utils";
import type { Review } from "@/lib/api";
export function ReviewCard({ review }: { review: Review }) {
return (
<div className="p-6 rounded-xl bg-card border border-border shadow-sm text-right" dir="rtl">
{/* الرأس: المؤلف والتاريخ */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<span className="font-semibold text-foreground">{review.author_name}</span>
{review.verified && (
<span className="flex items-center gap-1 text-xs font-medium text-emerald-600 bg-emerald-50 px-2 py-0.5 rounded-full">
<CheckCircle2 className="w-3 h-3" />
عميل موثق
</span>
)}
</div>
<time className="text-sm text-muted-foreground">
{new Date(review.created_at).toLocaleDateString("ar-EG", {
year: "numeric",
month: "short",
day: "numeric",
})}
</time>
</div>
{/* التقييم */}
<div className="flex gap-0.5 mb-3" aria-label={`${review.rating} من 5 نجوم`}>
{[1, 2, 3, 4, 5].map((star) => (
<Star
key={star}
className={cn(
"w-4 h-4",
star <= review.rating
? "fill-amber-400 text-amber-400"
: "fill-muted text-muted"
)}
/>
))}
</div>
{/* المحتوى */}
<h3 className="font-bold text-lg mb-2">{review.title}</h3>
<p className="text-muted-foreground leading-relaxed">{review.body}</p>
</div>
);
}
الخطوة 3: التكامل ومنظم البيانات (JSON-LD)
أخيرًا، قم بدمجه في صفحتك وأضف البيانات المنظمة (Structured Data) الهامة لـ Google.
// app/reviews/page.tsx
import { getReviews } from "@/lib/api";
import { ReviewCard } from "@/components/review-card";
export const metadata = {
title: "مراجعات العملاء",
description: "شاهد ما يقوله عملاؤنا.",
};
export default async function ReviewsPage() {
const reviews = await getReviews("معرف-النموذج-الخاص-بك");
const averageRating =
reviews.reduce((acc, r) => acc + r.rating, 0) / reviews.length;
// بيانات مقتطفات Google الغنية
const jsonLd = {
"@context": "https://schema.org",
"@type": "Product",
name: "منصة Acme SaaS",
aggregateRating: {
"@type": "AggregateRating",
ratingValue: averageRating.toFixed(1),
reviewCount: reviews.length,
},
};
return (
<section className="container py-12" dir="rtl">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<h1 className="text-4xl font-extrabold tracking-tight mb-8">
محبوب من قبل أكثر من {reviews.length} مطور
</h1>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{reviews.map((review) => (
<ReviewCard key={review.id} review={review} />
))}
</div>
</section>
);
}
الخاتمة
من خلال التحكم في واجهة المستخدم، تضمن أن مراجعاتك تبني الثقة لك أنت، وليس لمنصة المراجعات.
هذا النهج:
- أسرع: لا توجد نصوص برمجية ثقيلة لجهات خارجية.
- أنظف: يتطابق تمامًا مع علامتك التجارية.
- أذكى: رصيد SEO الكامل يذهب إلى نطاقك.
هل أنت مستعد للبناء؟ احصل على مفتاح API الخاص بك من لوحة التحكم وابدأ في الإطلاق.