Skip to main content
Ayrshare Connect विजेट हमारे लिंकिंग बटन आपके अपने डैशबोर्ड के अंदर रख देता है। आप एक script लोड करते हैं, अपने लेआउट में जहाँ कोई नेटवर्क आता है वहाँ एक slot डालते हैं, और हम वहाँ एक ऐसा बटन render करते हैं जो पहले से दिखाता है कि अकाउंट कनेक्टेड है या नहीं। आपका उपयोगकर्ता उस पर क्लिक करता है और आपका पेज छोड़े बिना अकाउंट लिंक करता है — अधिकतम एक पॉपअप, वह भी नेटवर्क का अपना। आपको कोई पॉपअप handling, कोई OAuth callbacks, कोई session refresh, और कोई प्रति-नेटवर्क logic नहीं लिखनी पड़ती। जब कोई नेटवर्क अपनी तरफ़ कुछ बदलता है, तो फ़िक्स हमारे deploy करते ही हमारे फ़्रेमों के अंदर पहुँच जाता है; आप कुछ भी redeploy नहीं करते।

आपको कौन सा सरफ़ेस चाहिए

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

एम्बेडेड फ़्रेम: हमारे tiles आपके अपने लेआउट के अंदर render किए गए, प्रति नेटवर्क एक slot या कई के लिए एक slot।

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

आपका अपना बटन: बटन आप render करते हैं, और हमारा एक संक्षिप्त पॉपअप नेटवर्क को संभालता है।

The hosted social linking page showing every available network

होस्टेड लिंकिंग पेज: हमारे द्वारा होस्ट किया गया पेज, आपके लोगो और रंगों के साथ, जिसका उपयोग करने के लिए आपका उपयोगकर्ता आपका ऐप छोड़ता है।

विजेट की दोनों rows एक ही इंटीग्रेशन हैं, दो नहीं। एक ही init आपको दोनों देता है: जहाँ आप हमारे बटन चाहते हैं वहाँ फ़्रेम mount करें, और बाक़ी हर जगह अपने बटन से popup() कॉल करें। वे एक ही सेशन साझा करते हैं और एक ही handlers पर रिपोर्ट करते हैं।डायरेक्ट मोड वही पॉपअप है बिना हमारी स्क्रिप्ट के — सख़्त Content-Security-Policy वाले पेज, server-rendered पेज, या native ऐप के लिए। वहाँ पॉपअप आप स्वयं खोलते और देखते हैं।

Script जोड़ें

कोई version और उसका hash pin करें, या बिना hash के कोई channel track करें। दोनों कभी नहीं — बदलते रहने वाले URL पर integrity attribute हमारी अगली release पर काम करना बंद कर देता है, क्योंकि वह जिस फ़ाइल का नाम लेता है वह वैध रूप से बदल चुकी होती है।
Pinned version
Tracking v1
v1 वह channel है जिसकी अनुशंसा की जाती है। यह फ़िक्स अपनाता है लेकिन कभी breaking change पार नहीं करता। latest परिभाषा से ही major versions पार करता है, इसलिए वह अंततः आपके पेज को ऐसा version थमा देगा जिसके व्यवहार की आपने समीक्षा नहीं की है। हर version का hash manifest.json में प्रकाशित होता है, जो यह भी बताता है कि हर channel वर्तमान में क्या serve कर रहा है:
manifest.json
हर bundle की शुरुआत में भी एक comment होता है जो उसका अपना version बताता है — यह हमें बताने का सबसे तेज़ तरीक़ा कि कोई पेज वास्तव में क्या चला रहा है:

Content-Security-Policy

यदि आपका पेज Content-Security-Policy भेजता है, तो उसे दो entries चाहिए, दोनों उस host के नाम पर जिससे आप script लोड करते हैं:
बस यही पूरी सूची है। हमारे लिए आपको कोई connect-src entry नहीं चाहिए — हमारे फ़्रेम हमारे API तक अपने अंदर से पहुँचते हैं, आपके पेज से नहीं — और पॉपअप के लिए कोई entry नहीं, जो top-level windows हैं जिन पर आपकी policy लागू नहीं होती। दोनों entries को मापा गया है: script-src हटाने से script ब्लॉक होती है, और frame-src हटाने से फ़्रेम।

एक instance शुरू करें

session एकमात्र आवश्यक option है। इसे प्रति instance एक बार कॉल किया जाता है, प्रति mount एक बार नहीं, और इसे mode: "connect" के साथ Link Session बनाएँ के प्रति आपके backend की प्रतिक्रिया — { sessionId, token, expiresAt } — बिल्कुल जैसी आई वैसी लौटानी होगी।
Your page
Your backend
विजेट सेशन कोई network नहीं बताता — यह आपके अकाउंट द्वारा अनुमत हर नेटवर्क को अधिकृत करता है, और कौन से दिखाई देते हैं यह प्रति mount, आपके पेज में तय होता है। यह एक origin ज़रूर ले जाता है, जो एकमात्र चीज़ है जिससे फ़्रेम render होते ही हैं: फ़्रेम उसे embed करने वाले पेज की तुलना उस मान से करता है और कहीं और render करने से इनकार कर देता है।
सेशन अपने server पर बनाएँ। कॉल को आपकी API Key चाहिए, और जो token यह लौटाता है वह आपके उपयोगकर्ता को उनके User Profile में साइन इन कर देता है — इसे पासवर्ड की तरह मानें।
Token की समाप्ति से पहले हम session को फिर से कॉल करते हैं, ताकि पूरे दिन खुला छोड़ा गया पेज भी काम करता रहे। जो कॉल reject होती है, या कोई token नहीं लौटाती, उसका दो बार और पुनः प्रयास किया जाता है — 0.5s बाद, फिर 1s बाद — इससे पहले कि हम हार मानकर error emit करें। यानी एक refresh की लागत आपके endpoint पर अधिकतम तीन कॉल है।

एक slot mount करें

प्रति slot एक mount। एक नेटवर्क माँगें, कई, या वह सब कुछ जो सेशन अनुमति देता है — granularity आपकी है, इसलिए slot किसी मौजूदा टेबल की एक row भी हो सकता है या सब कुछ रखने वाला एक panel।
mount एक CSS selector या element लेता है, और { unmount, element } लौटाता है। यदि target किसी से match नहीं करता तो यह throw करता है — जो लगभग हमेशा ऐसा slot होता है जो अभी मौजूद नहीं है, इसलिए अपने markup के document में आने के बाद mount करें। हर mount एक iframe है। वह अपनी ऊँचाई हमें रिपोर्ट करता है और हम उसे उसके अनुसार resize करते हैं, इसलिए हमारी सामग्री बदलने पर आपका लेआउट reflow होता है; maxHeight से आगे फ़्रेम आपके पेज से बाहर निकलने के बजाय अंदर ही scroll करता है। हमारा समर्थित सबसे संकीर्ण slot 300px है। Network keys Ayrshare की अपनी हैं, और alias spellings भी काम करती हैं: instagram और instagramapi दोनों का अर्थ instagramApi है, और x का अर्थ twitter। जो key कोई नेटवर्क नहीं है, वह कोई tile render नहीं करती।

आपका अपना बटन

जो ग्राहक हमारे किसी फ़्रेम के बजाय अपना बटन इस्तेमाल करना पसंद करे, वह इसके बजाय popup कॉल करता है। यह वही फ़्लो, उसी सेशन पर चलाता है, और उन्हीं handlers पर रिपोर्ट करता है।
इसे सीधे click handler के अंदर कॉल करें, इससे पहले कुछ भी await किए बिना। ब्राउज़र पॉपअप की अनुमति केवल तब तक देता है जब तक वह आपके उपयोगकर्ता के क्लिक को process कर रहा होता है, और वह अनुमति किसी await के बाद नहीं बचती। वैसे भी कुछ await करने की ज़रूरत नहीं है — सेशन init पर बन चुका था।
popup { close(), network } लौटाता है, और हमेशा एक handle लौटाता है — ब्लॉक हुए पॉपअप के बाद भी, जहाँ close() कुछ नहीं करता — ताकि आपके कोड को close() कॉल करने से पहले कभी null-check न करना पड़े। यहाँ हर नेटवर्क काम करता है, उन नेटवर्कों समेत जिन्हें फ़्रेम अपने ही panel के अंदर पूरा करता है: Facebook अपना hand-off explainer पॉपअप में दिखाता है, Bluesky और X अपना credential फ़ॉर्म दिखाते हैं, और LinkedIn, Pinterest, YouTube और Google Business नेटवर्क तक जाकर लौटते हैं। यह उन तीन चीज़ों के लिए synchronously throw करता है जो programming errors हैं — कोई network नहीं, destroy किया हुआ instance, या ऐसा सेशन जो अभी resolve नहीं हुआ है। ब्लॉक हुआ पॉपअप उनमें से नहीं है: वह reason: "popupBlocked" के साथ error emit करता है, क्योंकि आपके उपयोगकर्ता ने कुछ ग़लत नहीं किया। एक समय में अधिकतम एक पॉपअप खुला रहता है। दूसरी कॉल पहले को बंद कर देती है और उस पर reason: "superseded" के साथ cancelled रिपोर्ट करती है। हमारे किसी फ़्रेम द्वारा खोला गया पॉपअप अलग चीज़ है और उसे कभी छुआ नहीं जाता, इसलिए आपका बटन किसी mounted slot के अंदर चल रहे फ़्लो को रद्द नहीं कर सकता।
सेशन किसी नेटवर्क को लिंक कर सकता है या नहीं, यह server का जवाब है, script का नहीं। Bluesky तक सीमित सेशन से LinkedIn माँगने पर पॉपअप में एक इनकार render होता है और वह error के रूप में रिपोर्ट होता है। Script केवल यह जाँचती है कि कोई नेटवर्क बताया गया था या नहीं।

React

Script framework-free है, इसलिए React को हमसे कुछ ख़ास नहीं चाहिए — लेकिन उसके lifecycle की चार बातें पहली ही बार में सही कर लेना उचित है। Script को एक बार लोड करें, अपने component tree के बाहर। Next.js में वह आपके root layout में next/script है; Vite या Create React App में वह index.html में एक टैग है। इसे प्रति component लोड करना हर mount पर उसे फिर से चलाता है।
ConnectAccounts.jsx
destroy() के बाद instance का पुन: उपयोग कभी न करें। destroy किया हुआ instance destroy ही रहता है — उस पर popup() throw करता है, और mount() उसे वापस नहीं लाएगा। अगले effect run में नया instance बनाएँ, जो ऊपर का कोड यही करता है।
उस pattern के दो परिणाम हैं, और दोनों में से कोई bug नहीं है:
  • development में आपको session callback दो बार fire होता दिखेगा। React का Strict Mode effects को mount → unmount → mount क्रम में चलाता है, इसलिए instance बनता है, destroy होता है और फिर बनता है। ऊपर का cleanup इसे सुरक्षित बनाता है; dev में इसकी लागत आपके backend पर एक अतिरिक्त कॉल है और production में शून्य।
  • effect की dependencies स्थिर रखें। parent render से सीधे mount में पास किया गया array literal हर बार नया मान होता है, इसलिए उस पर निर्भर effect हर render पर विजेट को तोड़कर फिर से बनाता है। इसे memoize करें, या ऊपर की तरह स्थिर रखें।

Events

on से subscribe करें, जो एक unsubscribe फ़ंक्शन लौटाता है। Handlers को event का payload और वह mount मिलता है जिससे वह आया; off(name, handler) वही काम करता है जब आप handler को नाम देना पसंद करें।
दस events। हर एक में network होता है, सिवाय ready के, और उस एक तरह के error के जो किसी नेटवर्क के बारे में है ही नहीं — नीचे देखें error के दो स्रोत हैं। उनमें से चार अंत हैं — success, unlinked, error और cancelled — और प्रति प्रयास ठीक एक ही आता है। closed एक lifecycle सूचना है जो किसी अंत के बाद आती है, स्वयं अंत नहीं। click किसी भी linking काम के शुरू होने से पहले fire होता है, इसलिए वह ऐसा क्लिक भी रिपोर्ट करता है जिसे ब्लॉक हुआ पॉपअप या मृत सेशन आगे चलकर ठुकरा देता है। आपकी अपनी analytics के लिए यही event है; started वह है जिसका अर्थ है कि प्रयास वाक़ई चल रहा है।

Reasons

error के दो स्रोत हैं

उनमें से केवल एक link की विफलता है, और वे अलग-अलग फ़ील्ड ले जाते हैं।
  • Link error में network, code और वह mount होता है जिससे वह आया।
  • Session error — हम आपका सेशन बना या refresh नहीं कर पाए — में केवल message होता है, क्योंकि उस समय कुछ भी लिंक नहीं हो रहा था।
Defensive तरीक़े से destructure करें: दूसरी तरह पर code और network undefined होते हैं।

state आपको polling से बचाता है

state किसी प्रयास की रिपोर्ट के बजाय data channel है। हर फ़्रेम mount होते समय प्रति नेटवर्क एक emit करता है, जिसमें उस नेटवर्क का वर्तमान state और since timestamp होता है जबसे वह उसे धारण किए है, और हर बार जब कोई state बदलता है तब एक और — हमारी तरफ़ से शुरू होने वाले बदलावों समेत, जैसे किसी token का मरकर relink-required में बदल जाना। इसलिए आप बिना कुछ भी poll किए विजेट से अपना पूरा UI चला सकते हैं। मान वही enum हैं जो GET /profiles include=state के साथ लौटाता है: linked, unlinked, identityVerificationRequired, restricted, rateLimited, suspended।

अनलिंक करना

हमारे tiles लिंक के साथ-साथ अनलिंक भी करते हैं। आपका उपयोगकर्ता किसी कनेक्टेड नेटवर्क पर क्लिक करता है, पुष्टि करता है, और अकाउंट हटा दिया जाता है:
  1. click, action: "unlink" के साथ fire होता है।
  2. हटाना सेव हो जाने पर unlinked fire होता है।
जो अनलिंक विफल होता है वह error रिपोर्ट करता है, और जिससे आपका उपयोगकर्ता confirm चरण पर पीछे हट जाता है वह cancelled। कोई अलग unlink-failed event नहीं है।

Appearance

किसी ग्राहक की stylesheet cross-origin फ़्रेम के अंदर नहीं पहुँच सकती, इसलिए styling ऐसे data के रूप में जाती है जिसे हम उसके भीतर लागू करते हैं। appearance को init में CSS custom properties के रूप में पास करें; जो हमें नहीं मिलती वह हर एक हमारा डिफ़ॉल्ट रखती है।
रंग जोड़ियों में सेट करें। बिना foreground token के background token ही एकमात्र तरीक़ा है जिससे यह कुछ अपठनीय बना सकता है: --ayr-connect-surface-bg को अकेले गहरे मान पर सेट करें और हमारा डिफ़ॉल्ट --ayr-connect-surface-fg फिर भी गहरा navy रहेगा। दूसरा आधा आपके लिए कोई नहीं भाँप सकता।
बिल्कुल कोई appearance न होने पर, हर token अपना डिफ़ॉल्ट रखता है और फ़्रेम ऐसा दिखता है:
Three Ayrshare Connect tiles with the default appearance

डिफ़ॉल्ट tokens: सफ़ेद surfaces, गहरा navy टेक्स्ट, indigo accent, 8px radius।

मुट्ठी भर tokens पास करें और वही फ़्रेम आपका palette अपना लेता है। यह उदाहरण surfaces को हल्का नीला करता है, टेक्स्ट और accent को उसके अनुरूप गहरा करता है, और कोनों को थोड़ा और गोल:
Three Ayrshare Connect tiles restyled with pale blue surfaces and a deeper blue accent

ऊपर के tokens लागू होने के बाद वही तीन tiles।

एक ही palette है और कोई light/dark preset नहीं। कुछ भी prefers-color-scheme पर आधारित नहीं है, जानबूझकर — आपके पेज की थीम आपके उपयोगकर्ता के operating system से मेल न खाती हो सकती है, और कोई media query आपके चुने रंगों को चुपचाप पछाड़ देती। Dark डैशबोर्ड को dark मान देकर थीम किया जाता है। यह token सूची एक समर्थित contract है जिसे हम versions के आर-पार बनाए रखते हैं।

Tokens

जो मान अपने token के लिए वैध CSS नहीं है, वह लागू होने के बजाय आपके console में चेतावनी के साथ नज़रअंदाज़ किया जाता है। यह जितना लगता है उससे अधिक मायने रखता है: --ayr-connect-spacing के लिए unit-रहित 8 एक बिल्कुल मासूम स्ट्रिंग है जो उसे पढ़ने वाली हर गणना को अमान्य कर देती और लेआउट ढहा देती, बिना कहीं किसी error के। लंबाइयों को unit दें।

Hand-Off स्क्रीन पर आपका अपना नाम

आपके उपयोगकर्ता को किसी नेटवर्क को सौंपने से पहले, हम एक छोटी स्क्रीन दिखाते हैं जिस पर लिखा होता है कि वे किसके माध्यम से कनेक्ट कर रहे हैं। दो hooks इसे आपका अपना बनाने देते हैं, और दोनों version-stable हैं। --ayr-connect-partner-name label सेट करता है। यह एकमात्र token है जिसका मान टेक्स्ट है, इसलिए इसे CSS स्ट्रिंग के रूप में quote करना होगा — बिना quote का मान अमान्य है और कुछ भी render नहीं करता:
लोगो कोई token नहीं है। हम mark को positioned, sized element के रूप में भेजते हैं और आप उसे ऊपर की तरह css के माध्यम से background-image से भरते हैं — ऐसा token जो हमारे document के अंदर से कोई image fetch कर सके, हम स्वीकार नहीं करते, इसलिए request आपके लिखे किसी rule से आती है, आपके हमें दिए किसी मान से नहीं।
[data-ayr-connect-partner-mark] और [data-ayr-connect-partner-name] नीचे दी गई custom-CSS चेतावनी के अपवाद हैं: ये दोनों selectors contract का हिस्सा हैं और हम इन्हें versions के आर-पार बनाए रखते हैं।

कस्टम CSS

css एक ऐसी स्ट्रिंग लेता है जो हर फ़्रेम के अंदर लागू होती है, उन मामलों के लिए जिन्हें tokens कवर नहीं करते।
कस्टम CSS versions के आर-पार समर्थित नहीं है। इसके selectors हमारे आंतरिक markup को target करते हैं, जो releases के बीच बदलता है — जो rule आज काम करता है वह किसी भी अपडेट के बाद चुपचाप match करना बंद कर सकता है। ऊपर का token contract वह हिस्सा है जिसे हम बनाए रखते हैं। यदि आप कस्टम CSS पर निर्भर हैं तो कोई version pin करें।
पॉपअप instance के appearance और css को बिल्कुल फ़्रेमों की तरह अपनाते हैं, ताकि आपका उपयोगकर्ता किसी फ़्लो के बीच में हमारे neutral डिफ़ॉल्ट प्रकट होते न देखे।

Ship करने से पहले जानने योग्य

popup() से खोले गए पॉपअप को यह नहीं बताया जा सकता कि token क्यों ठुकराया गया — ऐसा कहने के लिए उसे ऐसे origin पर भरोसा करना होगा जिसे उसने अभी validate नहीं किया है, जिसकी अनुमति हमारा security model नहीं देता। इसलिए मृत token ले जाने वाला पॉपअप बंद हो जाता है और error के बजाय reason: "popupClosed" के साथ cancelled के रूप में सामने आता है।व्यवहार में यह दुर्लभ है: silent refresh से पहले खोला गया पॉपअप काम करता रहता है, क्योंकि उसने खुलते समय अपना token validate कर लिया था। यदि आपको अस्पष्टीकृत popupClosed परिणाम दिखें, तो जाँचें कि आपका session endpoint ताज़ा सेशन लौटा रहा है।
चौदह mounts एक token साझा करते हैं और आपके backend पर एक कॉल की लागत लगाते हैं, चौदह नहीं। यदि आप अलग-अलग scope वाले slots चाहते हैं — उनमें से कुछ पर अलग allowedSocial — तो किसी mount से उसे संकीर्ण करने की अपेक्षा करने के बजाय अपने सेशन के साथ दूसरा init चलाएँ।
हर सेशन वह origin ले जाता है जिस पर आपका पेज चलता है, और फ़्रेम कुछ भी render करने से पहले उसे embed करने वाले पेज की तुलना उस मान से करता है। कहीं और embed किया गया फ़्रेम खाली रहता है और कोई events नहीं भेजता। register करने के लिए कोई allowlist नहीं है और configure करने के लिए कुछ नहीं — सेशन बनाते समय सही origin भेजें।
फ़्रेम अपनी ऊँचाई script को रिपोर्ट करते हैं, और script उन्हें resize करती है। आपका लेआउट बस reflow होता है। subscribe करने के लिए कोई resize event नहीं है, और आपकी तरफ़ मापने के लिए कुछ नहीं।

आवश्यकताएँ

  • Max Pack। विजेट सेशन एक connect-mode सेशन है, और Max Pack के बिना एक बनाने पर code: 504 लौटता है। यदि आपको बिना Max Pack वाले अकाउंट पर connect mode सक्षम कराना हो तो support से संपर्क करें।
  • हर सेशन पर एक origin — ठीक वही origin जिस पर आपका पेज चलता है। इसे छोड़ने पर code: 505 लौटता है; ऐसा मान जो https origin, custom scheme, या http://localhost नहीं है, code: 506 लौटाता है।
  • सेशन पर कोई network नहीं। वह पैरामीटर सेशन को इसके बजाय डायरेक्ट मोड बना देता है, और direct-mode सेशन का URL वह नहीं है जिसकी script अपेक्षा करती है।
ऊपर का हर code Link Session त्रुटियाँ संदर्भ में है, API द्वारा लौटाए जाने वाले सटीक message और उसके समाधान के साथ।