你需要哪种界面

嵌入式框架:我们的卡片渲染在你自己的布局内,每个网络一个插槽,或一个插槽容纳多个网络。

你自己的按钮:按钮由你渲染,我们的一个短暂弹窗处理社交网络。

托管关联页面:我们托管的页面,带有你的 logo 和颜色,你的用户要离开你的应用去使用它。
两个小组件行是同一个集成,而不是两个。一次
init 同时给你两者:在需要我们按钮的地方挂载
框架,在其他任何地方从你自己的按钮调用 popup()。它们共享同一个会话,并在同一组处理器上报告
结果。直连模式(Direct Mode)是不带我们脚本的同一个弹窗——
适用于带有严格 Content-Security-Policy 的页面、服务器端渲染的页面或原生应用。在那里由你自己
打开并监视弹窗。添加脚本
固定(pin)一个版本及其哈希,或不带哈希地跟随一个渠道。两者绝不要同时使用——在会变动的 URL 上 添加integrity 属性会在我们下一次发布时失效,因为它指向的文件已经合理地发生了变化。
Pinned version
Tracking v1
v1 是值得推荐的渠道。 它会获得修复,但绝不会跨越破坏性变更。latest 从定义上就会跨越
主版本,因此它终究会把一个你尚未审阅过其行为的版本交给你的页面。
每个版本的哈希都发布在
manifest.json 中,其中还标明了
每个渠道当前提供的版本:
manifest.json
Content-Security-Policy
如果你的页面发送 Content-Security-Policy,它需要两条条目,都指向你加载脚本的主机:connect-src 条目——我们的框架从其内部访问我们的 API,
而不是从你的页面——也不需要为弹窗添加条目,弹窗是顶层窗口,不受你的策略约束。这两条条目都
经过实际验证:移除 script-src 会阻止脚本,移除 frame-src 会阻止框架。
启动一个实例
session 是唯一必需的选项。它每个实例调用一次,而不是每次 mount 调用一次,并且必须把你的
后端对带 mode: "connect" 的创建 Link Session 调用的响应
——{ sessionId, token, expiresAt }——原样返回。
Your page
Your backend
network——它授权你的账户允许的所有网络,具体显示哪些由每次 mount 在你的
页面中决定。它确实携带一个 origin,而这正是让框架得以渲染的唯一条件:框架会将嵌入它的页面与
该值进行比对,在其他任何地方都拒绝渲染。
我们会在 token 过期之前再次调用 session,因此在一个整天开着的页面上小组件也能持续工作。如果
调用被拒绝或未返回 token,会再重试两次——分别在 0.5 秒和 1 秒之后——然后我们放弃并发出
error。因此一次刷新最多花费三次对你端点的调用。
挂载插槽
每个插槽一次mount。可以请求一个网络、多个网络,或会话允许的所有网络——粒度由你决定,因此
一个插槽可以是现有表格中的一行,也可以是容纳所有内容的一个面板。
mount 接受 CSS 选择器或元素,并返回 { unmount, element }。如果目标没有匹配到任何内容,它会
抛出异常——这几乎总是因为插槽还不存在,所以请在你的标记进入文档之后再 mount。
每次 mount 都是一个 iframe。它会向我们报告自身高度,我们据此调整其大小,因此你的布局会随我们
内容的变化而重排;超过 maxHeight 时,框架改为内部滚动,而不会溢出你的页面。我们支持的最窄
插槽是 300px。
网络键名使用 Ayrshare 自己的名称,别名拼写同样有效:instagram 和 instagramapi 都表示
instagramApi,x 表示 twitter。不是网络的键不会渲染任何卡片。
你自己的按钮
宁愿使用自己的按钮而不是我们框架的客户可以改为调用popup。它运行同样的流程、使用同一个会话,
并在同一组处理器上报告结果。
popup 返回 { close(), network },并且总是返回一个句柄——包括弹窗被拦截之后(此时
close() 什么也不做)——因此你的代码在调用 close() 之前永远不必做空值检查。
所有网络在这里都可用,包括那些在框架自身面板内完成的网络:Facebook 在弹窗中显示其交接说明,
Bluesky 和 X 显示它们的凭据表单,而 LinkedIn、Pinterest、YouTube 和 Google Business 会跳转到
网络并返回。
对三种属于编程错误的情况它会同步抛出异常——没有 network、实例已被销毁、或会话尚未解析完成。
弹窗被拦截不是其中之一:那会发出带 reason: "popupBlocked" 的 error,因为你的用户没有
做错任何事。
同一时间最多只有一个弹窗打开。第二次调用会关闭第一个弹窗,并在其上报告带 reason: "superseded"
的 cancelled。我们的框架打开的弹窗是另一回事,绝不会被触及,因此你的按钮无法取消在挂载的
插槽内运行的流程。
会话是否可以关联某个网络由服务器决定,而不是脚本。一个仅限 Bluesky 的会话被要求关联
LinkedIn 时,会在弹窗中渲染拒绝信息并报告为
error。脚本只检查是否指定了网络。React
脚本不依赖任何框架,因此 React 不需要我们做任何特殊处理——但它的生命周期有四件事值得第一次就 做对。 只加载一次脚本,且在你的组件树之外。在 Next.js 中是根布局里的next/script;在 Vite 或
Create React App 中是 index.html 里的一个标签。按组件加载会在每次挂载时重新运行它。
ConnectAccounts.jsx
- 在开发环境中你会看到 session 回调触发两次。 React 的 Strict Mode 以 mount → unmount → mount 的顺序运行 effect,因此实例会被创建、销毁、再创建。上面的清理让这一切是安全的;它在 开发环境多花一次对你后端的调用,在生产环境一次也不多。
- 保持 effect 依赖稳定。 从父级渲染直接传入
mount的数组字面量每次都是新值,因此依赖它的 effect 会在每次渲染时拆掉并重建小组件。请对它做 memoize,或像上面那样保持常量。
事件
用on 订阅,它返回一个取消订阅函数。处理器会收到事件负载以及事件来源的 mount;当你更愿意用
具名处理器时,off(name, handler) 完成同样的工作。
ready 之外每个都携带 network,另有一种与网络完全无关的 error 也不携带——
参见下方 error 有两个来源。
其中四个是结局——
success、unlinked、error 和 cancelled——每次尝试恰好到达一个。
closed 是跟在结局之后的生命周期通知,本身不是结局。
click 在任何关联工作开始之前触发,因此它也会报告那些随后被拦截的弹窗或失效会话拒绝的
点击。它是用于你自己的分析统计的事件;started 才意味着一次尝试真正在运行。
Reason 取值
error 有两个来源
其中只有一个是关联失败,且两者携带的字段不同。
- 关联错误携带
network、code以及它来源的 mount。 - 会话错误——我们无法创建或刷新你的会话——只携带
message,因为当时没有任何东西在被关联。
code 和 network 为 undefined。
state 让你免于轮询
state 是数据通道,而不是对某次尝试的报告。每个框架在挂载时会为每个网络发出一个 state,携带
该网络的当前状态以及它保持该状态起始的 since 时间戳;每当状态变化时再发出一个——包括源自
我们这一侧的变化,例如 token 失效进入需要重新关联的状态。因此你可以完全由小组件驱动你的 UI,
而无需轮询任何东西。
取值与 GET /profiles 带 include=state 返回的枚举相同:
linked、unlinked、identityVerificationRequired、restricted、rateLimited、suspended。
解除关联
我们的卡片既能关联也能解除关联。你的用户点击一个已连接的网络并确认,账号即被移除:click触发,带action: "unlink"。- 移除保存后,
unlinked触发。
error,用户在确认步骤退出的会报告 cancelled。没有单独的
“解除关联失败”事件。
外观
客户的样式表无法进入跨源框架,因此样式以数据的形式传输,由我们在框架内应用。将appearance
作为 CSS 自定义属性传给 init;我们没有收到的每一项都保持默认值。
appearance 时,每个 token 都保持默认值,框架看起来是这样:

默认 token:白色表面、深海军蓝文字、靛蓝强调色、8px 圆角。

应用上述 token 之后的同样三个卡片。
prefers-color-scheme,这是有意的——你页面
的主题未必与用户的操作系统一致,而媒体查询会悄悄推翻你选择的颜色。深色控制台通过提供深色取值来
设置主题。
这份 token 列表是我们跨版本保持的受支持契约。
Token 列表
对其 token 而言不是合法 CSS 的值会被忽略,并在你的控制台输出一条警告,而不会被应用。这比
听起来更重要:给
--ayr-connect-spacing 传一个不带单位的 8 是个完全无辜的字符串,但它会使
读取它的所有计算失效并让布局塌陷,而且任何地方都不会报错。请给长度带上单位。
在交接屏幕上显示你自己的名称
在把用户交给社交网络之前,我们会显示一个简短的屏幕,标明他们正通过谁进行连接。两个钩子让你把它 变成自己的,而且两者都跨版本稳定。--ayr-connect-partner-name 设置标签。它是唯一取值为文本的 token,因此必须作为 CSS 字符串
加引号——不带引号的值是非法的,什么也不会渲染:
css 用
background-image 来填充它,如上所示——我们不接受能从我们文档内部获取图片的 token,因此该请求
来自你编写的规则,而不是你传给我们的值。
[data-ayr-connect-partner-mark] 和 [data-ayr-connect-partner-name] 是下方自定义 CSS
注意事项的例外:这两个选择器是契约的一部分,我们会跨版本保留它们。自定义 CSS
css 接受一个应用于每个框架内部的字符串,用于 token 覆盖不到的情况。
appearance 和 css,因此你的用户不会在流程进行到一半时看到我们的
中性默认样式。
发布前值得了解的事
会话已过期的弹窗报告 cancelled 而不是 error
会话已过期的弹窗报告 cancelled 而不是 error
用
popup() 打开的弹窗无法被告知 token 被拒绝的原因——要说明原因,它就必须信任一个尚未
验证的来源,而我们的安全模型不允许这样做。因此携带失效 token 的弹窗会关闭,并以带
reason: "popupClosed" 的 cancelled 而非 error 呈现。实践中这种情况很少见:在静默刷新之前打开的弹窗会继续工作,因为它在打开时验证了自己的
token。如果你看到无法解释的 popupClosed 结果,请检查你的 session 端点是否返回了新鲜的
会话。每个实例一个会话,而不是每次 mount 一个
每个实例一个会话,而不是每次 mount 一个
十四个 mount 共享一个 token,只花费一次对你后端的调用,而不是十四次。如果你想要不同作用域的
插槽——其中一些使用不同的
allowedSocial——请运行第二个带有自己会话的 init,而不要指望
某个 mount 去收窄它。框架只在你声明的 origin 上渲染
框架只在你声明的 origin 上渲染
每个会话都携带你页面运行所在的
origin,框架在渲染任何内容之前会将嵌入它的页面与该值比对。
嵌入在其他地方的框架保持空白且不发送任何事件。没有需要注册的允许列表,也没有需要配置的东西
——在创建会话时发送正确的 origin 即可。高度已为你处理好,而且不是事件
高度已为你处理好,而且不是事件
框架向脚本报告自身高度,脚本据此调整框架大小。你的布局只管重排即可。没有可订阅的 resize
事件,你这一侧也没有任何需要测量的东西。
要求
- Max Pack。小组件会话是 connect 模式的会话,没有 Max Pack 创建会
返回
code: 504。如果你需要在没有 Max Pack 的账户上启用 connect 模式,请联系支持团队。 - 每个会话都要有
origin——你页面运行所在的确切 origin。省略它返回code: 505;不是httpsorigin、自定义 scheme 或http://localhost的值返回code: 506。 - 会话上不要有
network。该参数会让会话变成直连模式, 而直连模式会话的 URL 不是脚本所期望的。