Skip to main content
تضع أداة Ayrshare Connect أزرار الربط الخاصة بنا داخل لوحة التحكم الخاصة بك. تحمّل سكربتًا واحدًا، وتضع فتحة (slot) حيثما يليق موضع شبكة في تخطيطك، فنعرض هناك زرًا يُظهر مسبقًا ما إذا كان الحساب متصلًا. ينقر مستخدمك عليه ويربط الحساب دون مغادرة صفحتك — على الأكثر نافذة منبثقة واحدة، هي نافذة الشبكة نفسها. أنت لا تكتب أي معالجة للنوافذ المنبثقة، ولا استدعاءات OAuth راجعة، ولا تحديثًا للجلسة، ولا منطقًا خاصًا بكل شبكة. وعندما تغيّر شبكة شيئًا من جانبها، يصل الإصلاح داخل إطاراتنا لحظة نشرنا له؛ وأنت لا تعيد نشر أي شيء.

أي سطح تريد

A customer dashboard with Ayrshare Connect tiles for Instagram, TikTok and LinkedIn embedded in a card

الإطارات المضمّنة: بطاقاتنا معروضة داخل تخطيطك، فتحة لكل شبكة أو فتحة واحدة لعدة شبكات.

A customer dashboard with its own Connect buttons and an Ayrshare popup showing the Facebook hand-off screen

زرك الخاص: أنت تعرض الزر، ونافذة منبثقة وجيزة من عندنا تتولى الشبكة.

The hosted social linking page showing every available network

صفحة الربط المستضافة: صفحة نستضيفها نحن، تحمل شعارك وألوانك، يغادر مستخدمك تطبيقك لاستخدامها.

صفّا الأداة هما تكامل واحد لا اثنان. استدعاء init واحد يمنحك الاثنين معًا: ركّب الإطارات حيث تريد أزرارنا، واستدعِ popup() من زرك الخاص في أي مكان آخر. يتشاركان جلسة واحدة ويبلّغان على المعالجات نفسها.الوضع المباشر (Direct mode) هو النافذة المنبثقة نفسها دون السكربت الخاص بنا — لصفحة ذات Content-Security-Policy صارمة، أو صفحة تُعرض من الخادم، أو تطبيق أصلي. هناك تفتح النافذة المنبثقة وتراقبها بنفسك.

إضافة السكربت

ثبّت إصدارًا مع الـ hash الخاص به، أو تتبّع قناة دون hash. لا تجمع بينهما أبدًا — فسمة integrity على عنوان URL متحرك تتوقف عن العمل عند إصدارنا التالي، لأن الملف الذي تُسمّيه قد تغيّر تغيّرًا مشروعًا.
Pinned version
Tracking v1
v1 هي القناة التي نوصي بها. تلتقط الإصلاحات لكنها لا تعبر أبدًا تغييرًا كاسرًا. أما latest فتعبر الإصدارات الرئيسية بحكم تعريفها، لذا ستسلّم صفحتك في نهاية المطاف إصدارًا لم تراجع سلوكه. يُنشر hash كل إصدار في manifest.json، الذي يُسمّي أيضًا ما تقدّمه كل قناة حاليًا:
manifest.json
تبدأ كل حزمة أيضًا بتعليق يُسمّي إصدارها، وهو أسرع وسيلة لإخبارنا بما تشغّله صفحة فعليًا:

Content-Security-Policy

إذا كانت صفحتك ترسل Content-Security-Policy، فهي تحتاج إلى إدخالين، كلاهما يُسمّي المضيف الذي تحمّل السكربت منه:
هذه هي القائمة بأكملها. لا تحتاج إلى أي إدخال connect-src لأجلنا — تصل إطاراتنا إلى API الخاصة بنا من داخلها هي، لا من صفحتك — ولا إدخال للنوافذ المنبثقة، فهي نوافذ من المستوى الأعلى لا تحكمها سياستك. كلا الإدخالين مُقاس أثرهما: إزالة script-src تحجب السكربت، وإزالة frame-src تحجب الإطار.

بدء نسخة (Instance)

session هو الخيار الوحيد المطلوب. يُستدعى مرة واحدة لكل نسخة، لا مرة لكل تركيب (mount)، ويجب أن يعيد استجابة خادمك الخلفي لـ إنشاء Link Session مع mode: "connect" — ‏{ sessionId, token, expiresAt } — تمامًا كما أُعيدت.
Your page
Your backend
جلسة الأداة لا تُسمّي أي network — فهي تفوّض كل شبكة يسمح بها حسابك، ويُقرَّر ما يظهر منها عند كل تركيب، في صفحتك أنت. لكنها تحمل origin، وهو الشيء الوحيد الذي يجعل الإطارات تُعرض أصلًا: يتحقق الإطار من الصفحة التي تضمّنه مقابل تلك القيمة ويرفض العرض في أي مكان آخر.
أنشئ الجلسة على خادمك. الاستدعاء يحتاج إلى مفتاح API الخاص بك، والتوكن الذي يعيده يُسجّل دخول مستخدمك إلى User Profile الخاص به — تعامل معه كما تتعامل مع كلمة المرور.
نستدعي session مجددًا قبل انتهاء صلاحية التوكن، فتظل الأداة تعمل في صفحة مفتوحة طوال اليوم. الاستدعاء الذي يُرفض، أو لا يعيد توكنًا، تُعاد محاولته مرتين أخريين — بعد 0.5 ثانية ثم ثانية واحدة — قبل أن نستسلم ونُطلق error. أي أن التحديث الواحد يكلّف على الأكثر ثلاثة استدعاءات لنقطة النهاية الخاصة بك.

تركيب فتحة

استدعاء mount واحد لكل فتحة. اطلب شبكة واحدة أو عدة شبكات أو كل ما تسمح به الجلسة — فمستوى التفصيل بيدك، ويمكن أن تكون الفتحة صفًا واحدًا في جدول موجود أو لوحة واحدة تحوي كل شيء.
يقبل mount مُحدِّد CSS أو عنصرًا، ويعيد { unmount, element }. ويرمي خطأً إذا لم يطابق الهدف أي شيء — وهذا في الغالب فتحة لم توجد بعد، لذا ركّب بعد أن تكون علاماتك (markup) في المستند. كل تركيب هو iframe واحد. يُبلغنا عن ارتفاعه فنعيد تحجيمه ليطابقه، فيُعاد تدفق تخطيطك مع تغيّر محتوانا؛ وبعد maxHeight يتمرّر الإطار داخليًا بدلًا من أن يفيض خارج صفحتك. أضيق فتحة ندعمها هي 300px. مفاتيح الشبكات هي مفاتيح Ayrshare نفسها، وتعمل التهجئات البديلة أيضًا: instagram وinstagramapi كلاهما يعني instagramApi، وx يعني twitter. المفتاح الذي ليس شبكة لا يعرض أي بطاقة.

زرك الخاص

العميل الذي يفضّل استخدام زره الخاص بدلًا من أحد إطاراتنا يستدعي popup بدلًا من ذلك. فهو يشغّل التدفق نفسه، على الجلسة نفسها، ويبلّغ على المعالجات نفسها.
استدعه مباشرةً داخل معالج النقر، دون أي await قبله. لا يسمح المتصفح بنافذة منبثقة إلا وهو لا يزال يعالج نقرة مستخدمك، وهذا الإذن لا ينجو من await. ولا شيء يحتاج إلى انتظار على أي حال — فالجلسة أُنشئت عند init.
يعيد popup القيمة { close(), network }، ويعيد دائمًا مقبضًا — حتى بعد نافذة منبثقة محجوبة، حيث لا يفعل close() شيئًا — بحيث لا تضطر شيفرتك أبدًا إلى فحص القيمة الفارغة قبل استدعاء close(). كل شبكة تعمل هنا، بما فيها الشبكات التي يُنهي الإطار عمله فيها داخل لوحته: يعرض Facebook شاشة شرح التسليم في النافذة المنبثقة، ويعرض Bluesky وX نموذج بيانات الاعتماد، بينما تخرج LinkedIn وPinterest وYouTube وGoogle Business إلى الشبكة وتعود. يرمي بشكل متزامن للأمور الثلاثة التي تُعدّ أخطاء برمجية — لا network، أو نسخة مدمّرة، أو جلسة لم تُحلّ بعد. أما النافذة المنبثقة المحجوبة فهي ليست منها: تلك تُطلق error مع reason: "popupBlocked"، لأن مستخدمك لم يرتكب أي خطأ. نافذة منبثقة واحدة على الأكثر تكون مفتوحة في أي لحظة. الاستدعاء الثاني يُغلق الأولى ويبلّغ عنها بـ cancelled مع reason: "superseded". أما النافذة المنبثقة التي فتحها أحد إطاراتنا فهي شيء مختلف ولا تُمسّ أبدًا، فلا يمكن لزرك أن يُلغي تدفقًا يجري داخل فتحة مركّبة.
ما إذا كان يجوز للجلسة ربط شبكة ما هو جواب الخادم، لا السكربت. الجلسة المحصورة في Bluesky التي يُطلب منها LinkedIn تحصل على رفض يُعرض في النافذة المنبثقة ويُبلَّغ عنه كـ error. السكربت لا يتحقق إلا من أن شبكة قد سُمّيت أصلًا.

React

السكربت مستقل عن أطر العمل، لذا لا يحتاج React إلى أي شيء خاص منا — لكن أربعة أمور في دورة حياته تستحق ضبطها صحيحًا من المرة الأولى. حمّل السكربت مرة واحدة، خارج شجرة مكوّناتك. في Next.js يعني ذلك next/script في التخطيط الجذري؛ وفي Vite أو Create React App وسم في index.html. تحميله لكل مكوّن يعيد تشغيله عند كل تركيب.
ConnectAccounts.jsx
لا تُعِد استخدام نسخة بعد destroy() أبدًا. النسخة المدمّرة تبقى مدمّرة — يرمي popup() عليها خطأً، ولن يُعيدها mount() إلى الحياة. أنشئ نسخة جديدة في تشغيل الـ effect التالي، وهو ما تفعله الشيفرة أعلاه.
نتيجتان لهذا النمط، ولا واحدة منهما خلل:
  • في بيئة التطوير سترى استدعاء الجلسة يُطلق مرتين. يشغّل Strict Mode في React التأثيرات بترتيب تركيب ← تفكيك ← تركيب، فتُنشأ النسخة وتُدمّر وتُنشأ مجددًا. التنظيف أعلاه يجعل ذلك آمنًا؛ ويكلّف استدعاءً إضافيًا واحدًا لخادمك الخلفي في التطوير ولا شيء في الإنتاج.
  • أبقِ اعتماديات الـ effect ثابتة. المصفوفة الحرفية المُمرَّرة مباشرةً إلى mount من عرض (render) للمكوّن الأب هي قيمة جديدة في كل مرة، فالـ effect الذي يعتمد عليها يفكّك الأداة ويعيد بناءها عند كل عرض. خزّنها بـ memoization، أو أبقِها ثابتة كما في المثال أعلاه.

الأحداث

اشترك بـ on، الذي يعيد دالة لإلغاء الاشتراك. تتلقى المعالجات حمولة الحدث والتركيب الذي جاء منه؛ ويؤدي off(name, handler) المهمة نفسها عندما تفضّل تسمية المعالج.
عشرة أحداث. كل واحد منها يحمل network باستثناء ready، وباستثناء النوع الوحيد من error الذي لا يتعلق بشبكة إطلاقًا — راجع error له مصدران أدناه. أربعة منها نهاياتsuccess وunlinked وerror وcancelled — ويصل واحد منها بالضبط لكل محاولة. أما closed فهو إشعار دورة حياة يتبع النهاية ولا يُعدّ نهاية بذاته. يُطلق click قبل بدء أي عمل ربط، فهو يبلّغ عن نقرة قد ترفضها لاحقًا نافذة منبثقة محجوبة أو جلسة ميتة. إنه الحدث المناسب لتحليلاتك الخاصة؛ أما started فهو الذي يعني أن محاولة تجري فعلًا.

الأسباب

لـ error مصدران

واحد منهما فقط هو فشل ربط، ويحملان حقولًا مختلفة.
  • خطأ الربط يحمل network وcode والتركيب الذي جاء منه.
  • خطأ الجلسة — تعذّر علينا إنشاء جلستك أو تحديثها — يحمل message فقط، لأنه لم يكن هناك شيء يُربط في ذلك الوقت.
فكّك (destructure) بحذر: code وnetwork قيمتهما undefined في النوع الثاني.

state يُغنيك عن الاستطلاع

state هو قناة البيانات لا تقريرًا عن محاولة. يُطلق كل إطار حدثًا واحدًا لكل شبكة عند تركيبه، يحمل الحالة الراهنة لتلك الشبكة وطابع since الزمني الذي تحملها منه، وحدثًا آخر كلما تغيّرت حالة — بما في ذلك التغييرات التي تنشأ من جانبنا، مثل موت توكن إلى حالة تتطلب إعادة الربط. فبإمكانك إذًا تشغيل واجهتك كلها من الأداة دون استطلاع أي شيء. القيم هي التعداد (enum) نفسه الذي تعيده GET /profiles مع include=state: ‏linked وunlinked وidentityVerificationRequired وrestricted وrateLimited وsuspended.

فك الربط

بطاقاتنا تفكّ الربط كما تربط. ينقر مستخدمك على شبكة متصلة، ويؤكد، فيُزال الحساب:
  1. يُطلق click مع action: "unlink".
  2. يُطلق unlinked بمجرد حفظ الإزالة.
فك الربط الذي يفشل يبلّغ عنه error، والذي يتراجع عنه مستخدمك عند خطوة التأكيد يبلّغ عنه cancelled. لا يوجد حدث منفصل لفشل فك الربط.

المظهر

لا تستطيع ورقة أنماط العميل الوصول إلى داخل إطار عابر الأصول (cross-origin)، لذا ينتقل التنسيق كبيانات نطبّقها نحن داخله. مرّر appearance إلى init كخصائص CSS مخصصة؛ وكل خاصية لا نتلقاها تحتفظ بقيمتنا الافتراضية.
اضبط الألوان أزواجًا. رمز خلفية دون رمز مقدّمة إلى جانبه هو الطريقة الوحيدة لجعل هذا ينتج شيئًا غير مقروء: اضبط --ayr-connect-surface-bg على قيمة داكنة وحده وسيبقى --ayr-connect-surface-fg الافتراضي لدينا كحليًا داكنًا. لا شيء يستطيع استنتاج النصف الآخر نيابةً عنك.
من دون أي appearance إطلاقًا، يحتفظ كل رمز بقيمته الافتراضية ويبدو الإطار هكذا:
Three Ayrshare Connect tiles with the default appearance

الرموز الافتراضية: أسطح بيضاء، ونص كحلي داكن، ولون مميز نيلي، ونصف قطر 8px.

مرّر حفنة من الرموز فيتخذ الإطار نفسه لوحة ألوانك. هذا المثال يجعل الأسطح زرقاء باهتة، ويعمّق النص واللون المميز ليطابقاها، ويزيد استدارة الزوايا قليلًا:
Three Ayrshare Connect tiles restyled with pale blue surfaces and a deeper blue accent

البطاقات الثلاث نفسها بعد تطبيق الرموز أعلاه.

هناك لوحة ألوان واحدة ولا إعداد مسبق فاتح/داكن. لا شيء يعتمد على prefers-color-scheme، عن قصد — فقد لا يطابق ثيم صفحتك نظام تشغيل مستخدمك، وكان استعلام وسائط سيتفوق بصمت على الألوان التي اخترتها. لوحة التحكم الداكنة تُظلَّل بتزويد قيم داكنة. قائمة الرموز هذه عقد مدعوم نحافظ عليه عبر الإصدارات.

الرموز

القيمة التي ليست CSS صالحًا لرمزها تُتجاهل، مع تحذير في الـ console لديك، بدلًا من أن تُطبَّق. وهذا أهم مما يبدو: القيمة 8 بلا وحدة لـ --ayr-connect-spacing سلسلة بريئة تمامًا كانت ستُبطل كل حساب يقرؤها وتُقوّض التخطيط، دون خطأ في أي مكان. أعطِ الأطوال وحدة.

اسمك الخاص على شاشة التسليم

قبل أن نسلّم مستخدمك إلى شبكة، نعرض شاشة قصيرة تُسمّي الجهة التي يتصل من خلالها. خطّافان يتيحان لك جعلها خاصتك، وكلاهما مستقر عبر الإصدارات. يضبط --ayr-connect-partner-name التسمية. وهو الرمز الوحيد الذي قيمته نص، لذا يجب اقتباسها كسلسلة CSS — القيمة غير المقتبسة غير صالحة ولا تعرض شيئًا إطلاقًا:
الشعار ليس رمزًا. نشحن العلامة كعنصر موضوع ومحدد الحجم وأنت تملؤه بـ background-image عبر css، كما في المثال أعلاه — فالرمز الذي يستطيع جلب صورة من داخل مستندنا ليس شيئًا نقبله، لذا يأتي الطلب من قاعدة كتبتها أنت لا من قيمة مرّرتها إلينا.
[data-ayr-connect-partner-mark] و[data-ayr-connect-partner-name] هما الاستثناء من تنبيه CSS المخصص أدناه: هذان المُحدِّدان جزء من العقد ونحافظ عليهما عبر الإصدارات.

CSS مخصص

يقبل css سلسلة تُطبَّق داخل كل إطار، للحالات التي لا تغطيها الرموز.
CSS المخصص غير مدعوم عبر الإصدارات. تستهدف مُحدِّداته علاماتنا الداخلية، التي تتغير بين الإصدارات — فالقاعدة التي تعمل اليوم قد تتوقف بصمت عن المطابقة بعد أي تحديث. عقد الرموز أعلاه هو الجزء الذي نحافظ عليه. ثبّت إصدارًا إن كنت تعتمد على CSS المخصص.
ترث النوافذ المنبثقة appearance وcss الخاصين بالنسخة تمامًا كما ترثهما الإطارات، فلا يشاهد مستخدمك افتراضياتنا المحايدة تظهر في منتصف تدفق.

يستحق المعرفة قبل الإطلاق

لا يمكن إخبار نافذة منبثقة فتحتها بـ popup() بسبب رفض توكن — فلكي تفعل ذلك سيكون عليها الوثوق بأصل لم تتحقق منه بعد، وهو ما لا يسمح به نموذجنا الأمني. لذا فإن النافذة المنبثقة التي تحمل توكنًا ميتًا تُغلق وتظهر كـ cancelled مع reason: "popupClosed" بدلًا من error.عمليًا هذا نادر: النافذة المنبثقة المفتوحة قبل تحديث صامت تستمر في العمل، لأنها تحققت من توكنها عند فتحها. إذا رأيت نتائج popupClosed غير مفسّرة، فتحقق من أن نقطة نهاية session لديك تعيد جلسة حديثة.
أربعة عشر تركيبًا تتشارك توكنًا واحدًا وتكلّف استدعاءً واحدًا لخادمك الخلفي، لا أربعة عشر. إذا أردت فتحات ذات نطاقات مختلفة — قيمة allowedSocial مختلفة على بعضها — فشغّل استدعاء init ثانيًا بجلسته الخاصة بدلًا من توقّع أن يضيّق التركيب النطاق.
تحمل كل جلسة origin الذي تعمل عليه صفحتك، ويقارن الإطار الصفحة التي تضمّنه بتلك القيمة قبل عرض أي شيء. الإطار المضمّن في مكان آخر يبقى فارغًا ولا يرسل أي أحداث. لا توجد قائمة سماح للتسجيل ولا شيء للإعداد — أرسل origin الصحيح عند إنشاء الجلسة.
تبلّغ الإطارات السكربت عن ارتفاعها، والسكربت يعيد تحجيمها. وتخطيطك يُعاد تدفقه فحسب. لا يوجد حدث لإعادة التحجيم تشترك فيه، ولا شيء تقيسه من جانبك.

المتطلبات

  • Max Pack. جلسة الأداة هي جلسة بوضع connect، وإنشاء واحدة دون Max Pack يعيد code: 504. تواصل مع الدعم إذا كنت بحاجة إلى تفعيل وضع connect على حساب من دونه.
  • origin على كل جلسة — الأصل الفعلي الذي تعمل عليه صفحتك. حذفه يعيد code: 505؛ والقيمة التي ليست أصل https أو مخططًا مخصصًا أو http://localhost تعيد code: 506.
  • لا network على الجلسة. هذا المعامل هو ما يجعل الجلسة وضعًا مباشرًا بدلًا من ذلك، وعنوان URL لجلسة الوضع المباشر ليس ما يتوقعه السكربت.
كل رمز أعلاه موجود في مرجع أخطاء Link Session، مع الرسالة الفعلية التي تعيدها API وما ينبغي فعله حيالها.