Qué superficie quieres

Frames incrustados: nuestras tarjetas renderizadas dentro de tu propio layout, un slot por red o un slot para varias.

Tu propio botón: tú renderizas el botón, y una breve ventana emergente nuestra se encarga de la red.

Página de vinculación alojada: una página alojada por nosotros, con tu logo y tus colores, que tu usuario abandona tu app para usar.
init te da ambas: monta
frames donde quieras nuestros botones y llama a popup() desde tu propio botón en el resto de
sitios. Comparten una misma sesión y reportan en los mismos handlers.El modo directo (Direct Mode) es la misma ventana emergente
sin nuestro script — para una página con una Content-Security-Policy estricta, una página
renderizada en servidor o una app nativa. Ahí abres y supervisas la ventana emergente tú mismo.Añade el script
Fija una versión y su hash, o sigue un canal sin él. Nunca ambas cosas — un atributointegrity en
una URL que se mueve deja de funcionar en nuestra siguiente versión, porque el archivo que nombra ha
cambiado legítimamente.
v1 es el canal recomendable. Recoge correcciones pero nunca cruza un cambio incompatible.
latest cruza versiones mayores por definición, así que en algún momento entregará a tu página una
versión cuyo comportamiento no has revisado.
El hash de cada versión se publica en
manifest.json, que también indica qué
sirve actualmente cada canal:
Content-Security-Policy
Si tu página envía una Content-Security-Policy, necesita dos entradas, ambas con el host desde el que cargas el script:connect-src para nosotros — nuestros frames
llegan a nuestra API desde dentro de sí mismos, no desde tu página — y ninguna entrada para
ventanas emergentes, que son ventanas de nivel superior que tu política no gobierna. Ambas
entradas están medidas: quitar script-src bloquea el script, y quitar frame-src bloquea el frame.
Inicia una instancia
session es la única opción obligatoria. Se llama una vez por instancia, no una vez por mount, y
debe devolver la respuesta de tu backend a
Crear una Link Session con mode: "connect" —
{ sessionId, token, expiresAt } — exactamente como llegó.
network — autoriza todas las redes que tu cuenta
permite, y cuáles aparecen se decide por mount, en tu página. Sí lleva un origin, que es lo único
que hace que los frames se rendericen: un frame comprueba la página que lo incrusta contra ese valor
y se niega a renderizarse en cualquier otro sitio.
Volvemos a llamar a session antes de que el token caduque, así que el widget sigue funcionando en
una página que se deja abierta todo el día. Una llamada que rechaza, o que no devuelve ningún token,
se reintenta dos veces más — a los 0,5 s y luego a 1 s — antes de rendirnos y emitir error. Así
que un refresco cuesta como mucho tres llamadas a tu endpoint.
Monta un slot
Unmount por slot. Pide una red, varias o todo lo que la sesión permita — la granularidad es tuya,
así que un slot puede ser una única fila de una tabla existente o un panel que lo contenga todo.
mount acepta un selector CSS o un elemento, y devuelve { unmount, element }. Lanza una excepción
si el destino no coincide con nada — que casi siempre es un slot que todavía no existe, así que monta
después de que tu marcado esté en el documento.
Cada mount es un iframe. Nos informa de su propia altura y lo redimensionamos para que coincida, de
modo que tu layout se reajusta cuando nuestro contenido cambia; pasado maxHeight el frame se
desplaza internamente en lugar de salirse de tu página. El slot más estrecho que admitimos es de
300px.
Las claves de red son las propias de Ayrshare, y las grafías alias también funcionan: instagram e
instagramapi significan ambas instagramApi, y x significa twitter. Una clave que no es una
red no renderiza ninguna tarjeta.
Tu propio botón
Un cliente que prefiera usar su propio botón en lugar de uno de nuestros frames llama apopup en
su lugar. Ejecuta el mismo flujo, sobre la misma sesión, y reporta en los mismos handlers.
popup devuelve { close(), network }, y siempre devuelve un handle — incluso tras una ventana
emergente bloqueada, donde close() no hace nada — de modo que tu código nunca tiene que comprobar
null antes de llamar a close().
Todas las redes funcionan aquí, incluidas las que un frame termina dentro de su propio panel:
Facebook muestra su pantalla explicativa de traspaso en la ventana emergente, Bluesky y X muestran su
formulario de credenciales, y LinkedIn, Pinterest, YouTube y Google Business salen a la red y
vuelven.
Lanza una excepción síncrona en los tres casos que son errores de programación — ningún network,
una instancia destruida, o una sesión que aún no se ha resuelto. Una ventana emergente bloqueada
no es uno de ellos: eso emite error con reason: "popupBlocked", porque tu usuario no hizo
nada mal.
Como mucho hay una ventana emergente abierta a la vez. Una segunda llamada cierra la primera y
reporta cancelled con reason: "superseded" sobre ella. Una ventana emergente abierta por uno de
nuestros frames es otra cosa y nunca se toca, así que tu botón no puede cancelar un flujo en
curso dentro de un slot montado.
error. El script solo comprueba que se haya nombrado alguna red.React
El script no depende de ningún framework, así que React no necesita nada especial de nosotros — pero hay cuatro cosas de su ciclo de vida que conviene hacer bien a la primera. Carga el script una vez, fuera de tu árbol de componentes. En Next.js eso esnext/script en tu
layout raíz; en Vite o Create React App es una etiqueta en index.html. Cargarlo por componente lo
vuelve a ejecutar en cada mount.
- En desarrollo verás el callback de sesión dispararse dos veces. El Strict Mode de React ejecuta los efectos mount → unmount → mount, así que la instancia se crea, se destruye y se vuelve a crear. La limpieza de arriba hace que eso sea seguro; cuesta una llamada extra a tu backend en desarrollo y ninguna en producción.
- Mantén estables las dependencias del efecto. Un array literal pasado directamente a
mountdesde el render de un padre es un valor nuevo cada vez, así que un efecto que dependa de él desmonta el widget y lo reconstruye en cada render. Memoízalo, o mantenlo constante como arriba.
Eventos
Suscríbete conon, que devuelve una función para cancelar la suscripción. Los handlers reciben el
payload del evento y el mount del que procede; off(name, handler) hace el mismo trabajo cuando
prefieres nombrar el handler.
network excepto ready, y excepto el único tipo de error que no
trata de ninguna red — consulta error tiene dos orígenes más abajo.
success, unlinked, error y cancelled — y llega exactamente
uno por intento. closed es un aviso de ciclo de vida que sigue a un final, no un final en sí.
click se dispara antes de que empiece cualquier trabajo de vinculación, así que reporta un clic
que una ventana emergente bloqueada o una sesión muerta rechazará después. Es el evento que usar para
tus propias analíticas; started es el que significa que un intento está realmente en marcha.
Razones
error tiene dos orígenes
Solo uno de ellos es un fallo de vinculación, y llevan campos distintos.
- Un error de vinculación lleva
network,codey el mount del que procede. - Un error de sesión — no pudimos crear o refrescar tu sesión — lleva solo
message, porque no se estaba vinculando nada en ese momento.
code y network son undefined en el segundo tipo.
state te ahorra el polling
state es el canal de datos, más que un informe sobre un intento. Cada frame emite uno por red al
montarse, con el estado actual de esa red y la marca de tiempo since desde la que lo mantiene, y
otro cada vez que un estado cambia — incluidos los cambios que se originan en nuestro lado, como
un token que muere y pasa a requerir revinculación. Así que puedes alimentar toda tu UI desde el
widget sin hacer polling de nada.
Los valores son el mismo enum que devuelve
GET /profiles con include=state: linked, unlinked,
identityVerificationRequired, restricted, rateLimited, suspended.
Desvincular
Nuestras tarjetas desvinculan además de vincular. Tu usuario hace clic en una red conectada, confirma, y la cuenta se elimina:clickse dispara conaction: "unlink".unlinkedse dispara una vez que la eliminación está guardada.
error, y una de la que tu usuario se echa atrás en el
paso de confirmación reporta cancelled. No hay un evento separado de desvinculación fallida.
Apariencia
La hoja de estilos de un cliente no puede llegar al interior de un frame cross-origin, así que los estilos viajan como datos que aplicamos dentro de él. Pasaappearance a init como propiedades
personalizadas de CSS; cada una que no recibamos conserva nuestro valor por defecto.
appearance, cada token conserva su valor por defecto y un frame tiene este aspecto:

Tokens por defecto: superficies blancas, texto azul marino oscuro, acento índigo, radio de 8px.

Las mismas tres tarjetas después de aplicar los tokens de arriba.
prefers-color-scheme, a
propósito — el tema de tu página puede no coincidir con el sistema operativo de tu usuario, y una
media query invalidaría silenciosamente los colores que elegiste. Un dashboard oscuro se tematiza
suministrando valores oscuros.
Esta lista de tokens es un contrato soportado que mantenemos entre versiones.
Los tokens
8 sin unidad para --ayr-connect-spacing
es una cadena perfectamente inocente que invalidaría cada cálculo que la lea y colapsaría el layout,
sin ningún error en ninguna parte. Dales unidad a las longitudes.
Tu propio nombre en la pantalla de traspaso
Antes de entregar tu usuario a una red, mostramos una breve pantalla que indica a través de quién se está conectando. Dos ganchos te permiten hacerla tuya, y ambos son estables entre versiones.--ayr-connect-partner-name establece la etiqueta. Es el único token cuyo valor es texto, así
que tiene que ir entrecomillado como una cadena CSS — un valor sin comillas es inválido y no
renderiza nada en absoluto:
background-image mediante css, como arriba — un token que pudiera cargar una
imagen desde dentro de nuestro documento no es algo que aceptemos, así que la petición procede de una
regla que escribiste tú y no de un valor que nos pasaste.
[data-ayr-connect-partner-mark] y [data-ayr-connect-partner-name] son la excepción a la
advertencia sobre CSS personalizado de abajo: estos dos selectores forman parte del contrato y los
mantenemos entre versiones.CSS personalizado
css acepta una cadena que se aplica dentro de cada frame, para los casos que los tokens no cubren.
appearance y el css de la instancia exactamente igual que los
frames, así que tu usuario no ve aparecer nuestros valores neutros por defecto a mitad de un flujo.
Cosas que conviene saber antes de lanzar
Una ventana emergente cuya sesión ha caducado reporta cancelled, no error
Una ventana emergente cuya sesión ha caducado reporta cancelled, no error
popup() no se le puede decir por qué se rechazó un
token — para hacerlo tendría que confiar en un origen que aún no ha validado, cosa que nuestro
modelo de seguridad no permite. Así que una ventana emergente con un token muerto se cierra y
aflora como cancelled con reason: "popupClosed" en lugar de error.En la práctica esto es raro: una ventana emergente abierta antes de un refresco silencioso sigue
funcionando, porque validó su token al abrirse. Si ves resultados popupClosed sin explicación,
comprueba que tu endpoint de session esté devolviendo una sesión nueva.Una sesión por instancia, no una por mount
Una sesión por instancia, no una por mount
allowedSocial distinto en algunos — ejecuta un segundo init
con su propia sesión en lugar de esperar que un mount la acote.Los frames solo se renderizan en el origin que declaraste
Los frames solo se renderizan en el origin que declaraste
origin en el que corre tu página, y un frame compara la página que lo
incrusta contra ese valor antes de renderizar nada. Un frame incrustado en otro sitio se queda en
blanco y no envía eventos. No hay ninguna allowlist que registrar ni nada que configurar — envía
el origin correcto al crear la sesión.La altura se gestiona por ti, y no es un evento
La altura se gestiona por ti, y no es un evento
Requisitos
- El Max Pack. Una sesión del widget es una sesión en modo connect, y
crear una sin el Max Pack devuelve
code: 504. Contacta con soporte si necesitas habilitar el modo connect en una cuenta sin él. - Un
originen cada sesión — el origen exacto en el que corre tu página. Omitirlo devuelvecode: 505; un valor que no sea un origenhttps, un esquema personalizado ohttp://localhostdevuelvecode: 506. - Ningún
networken la sesión. Ese parámetro es lo que convierte una sesión en modo directo, y la URL de una sesión en modo directo no es lo que el script espera.