React وNext.js
ثبّت المُحمِّل العام (public loader) مرة واحدة داخل تخطيط React أو Next.js يملكه العميل، ثم نظّفه بشكل مقصود.
ثبّت المُحمِّل العام (public loader) مرة واحدة داخل تخطيط React أو Next.js يملكه العميل، ثم نظّفه بشكل مقصود.
تجهيز النطاقات ونطاق التطبيق#
فعّل خيار إظهاره على موقعي للـ agent (صفحة الـ agent ← انشره الآن ← أداة الموقع)، وأضف عناوين النطاقات (origins) المحلية وعناوين المعاينة والإنتاج بدقة ضمن عناوين المواقع المسموح بها. حدّد ما إذا كان يجب أن تبقى أيقونة التشغيل ظاهرة عند كل تنقّل داخل العميل (التخطيط الجذري)، أم أن تظهر فقط ضمن مسارات محددة (تخطيط أو مكوّن متداخل).
Next.js App Router#
استخدم next/script في مكوّن يعرضه التخطيط الذي يملك أيقونة التشغيل. المعرّف المختصر (slug) آمن للكشف عنه؛ لا تستخدم مفتاح API ولا متغير بيئة سرّيًا.
import Script from "next/script";
export function AgentEmbed() {
return (
<Script
id="maf-agent"
src="https://makeagent.fast/embed.js?v=20261022-open"
strategy="afterInteractive"
data-agent="YOUR_SITE_SLUG"
data-position="right"
data-label="Ask us"
/>
);
}اعرض <AgentEmbed /> مرة واحدة في app/layout.tsx للحصول على agent يعمل في الموقع بالكامل، أو في تخطيط متداخل لمجموعة مسارات. لا تعرض نسخة منفصلة من كل مكوّن صفحة. الاستراتيجية afterInteractive تتجنب الوصول إلى DOM من جهة الخادم ولا تعطّل تحليل HTML الأولي.
في Next.js Pages Router، اعرض المكوّن نفسه مرة واحدة من pages/_app.tsx للحصول على سلوك يشمل الموقع كله. لا يكون عرضه من صفحة بعينها مناسبًا إلا عندما يجب إزالة الـ agent بمجرد مغادرة تلك الصفحة؛ وفي هذه الحالة استخدم نمط التأثير/التنظيف الصريح أدناه، لأن السكربت الخارجي بعد تحميله يكون قد أنشأ عناصر DOM خارج شجرة React.
React بدون Next.js#
أنشئ السكربت داخل تأثير (effect). يمنع معرّف السكربت الثابت الإدراج المكرر في وضع Strict Mode أثناء التطوير. إذا كان المكوّن مرتبطًا بمسار معين، فيجب أن يزيل التنظيف كلًا من السكربت والعنصر الجذري الذي أنشأه المُحمِّل.
import { useEffect } from "react";
const slug = "YOUR_SITE_SLUG";
export function AgentEmbed() {
useEffect(() => {
if (document.getElementById(`maf-embed-root-${slug}`)) return;
const script = document.createElement("script");
script.id = "maf-agent";
script.src = "https://makeagent.fast/embed.js?v=20261022-open";
script.dataset.agent = slug;
script.dataset.position = "right";
script.async = true;
document.body.appendChild(script);
return () => {
script.remove();
document.getElementById(`maf-embed-root-${slug}`)?.remove();
};
}, []);
return null;
}لعرض أيقونة التشغيل في الموقع بالكامل، ثبّت هذا المكوّن فوق جهاز التوجيه (router) وتجنّب إلغاء التثبيت المرتبط بالمسارات. يحافظ إبقاء العنصر الجذري على iframe والمحادثة أثناء التنقّل.
إعداد البيئة#
يمكن لمتغير عام يُحدَّد وقت البناء أن يحمل الـ slug لأنه ليس سريًا. تحقّق منه قبل العرض، وأبقِ مفاتيح MAF API الحقيقية وبيانات اعتماد المزوّدين على الخادم فقط. عند غياب الـ slug يحذّر المُحمِّل ثم يتوقف بدلًا من إنشاء أيقونة تشغيل.
إذا كان تطبيقك يخدم عدة مستأجرين (tenants) من عملائك عبر بناء React واحد، فلا تغيّر data-agent في سكربت نُفِّذ بالفعل. امنح المستأجر الحالي slug ثابتًا واحدًا، وأزل العنصر الجذري الخاص بالـ slug القديم أثناء تبديل المستأجر بعد المصادقة، ثم ثبّت سكربتًا جديدًا. لا تسمح أبدًا لمعامل استعلام غير موثوق باختيار slug يعود إلى مستأجر آخر.
التحقق من الترطيب (hydration) والتنقّل#
- حمّل مسارًا عامًا مباشرة وتأكد من ظهور أيقونة تشغيل واحدة.
- تنقّل من جهة العميل عبر المسارات التي يجب أن تحتفظ بها.
- في التثبيت المتداخل أو المرتبط بمسار، اخرج من المسار وتأكد من اختفاء السكربت والعنصر الجذري معًا، ثم عُد وتأكد من ظهور أيقونة تشغيل جديدة واحدة.
- افحص Network وCSP، وجرّب إرسال رسالة حقيقية.
- شغّل بناء الإنتاج؛ فوضع Strict Mode في التطوير وحده لا يمثل السلوك النهائي.
استكشاف الأخطاء وإصلاحها#
| العَرَض | الحل |
|---|---|
document is not defined | نُفّذ كود DOM أثناء SSR؛ انقله إلى useEffect أو استخدم next/script |
| ظهور أيقونتي تشغيل أو agent اثنين | هناك عدة slugs أو مكوّنات مثبّتة؛ أبقِ تخطيطًا واحدًا مالكًا |
| تبقى أيقونة التشغيل بعد مغادرة المسار | أزل maf-embed-root-SLUG في التنظيف، وليس السكربت فقط |
| تختفي أيقونة التشغيل عند كل تنقّل | ثبّتها في مستوى أعلى من شجرة التخطيط أو جهاز التوجيه |
| يعمل محليًا لكن لا يعمل في المعاينة/الإنتاج | أضف عنوان النطاق (origin) الدقيق لكل عملية نشر إلى قائمة السماح |
لا يتوفر حاليًا محوّل npm لـ React/Next منشور؛ تستخدم هذه الأمثلة المُحمِّل العام المدعوم الذي لا يعتمد على REST.