Skip to main content
O widget Ayrshare Connect coloca nossos botões de vinculação dentro do seu próprio dashboard. Você carrega um script, coloca um slot onde a rede pertence no seu layout, e nós renderizamos ali um botão que já mostra se a conta está conectada. Seu usuário clica nele e vincula a conta sem sair da sua página — no máximo um popup, o da própria rede. Você não escreve nenhum tratamento de popup, nenhum callback de OAuth, nenhum refresh de sessão e nenhuma lógica por rede. Quando uma rede muda algo do lado dela, a correção chega dentro dos nossos frames no momento em que fazemos o deploy; você não faz redeploy de nada.

Qual superfície você quer

Um dashboard de cliente com tiles do Ayrshare Connect para Instagram, TikTok e LinkedIn incorporados em um card

Frames incorporados: nossos tiles renderizados dentro do seu próprio layout, um slot por rede ou um slot para várias.

Um dashboard de cliente com seus próprios botões Connect e um popup da Ayrshare mostrando a tela de transição do Facebook

Seu próprio botão: você renderiza o botão, e um breve popup nosso cuida da rede.

A página de vinculação social hospedada mostrando todas as redes disponíveis

Página de vinculação hospedada: uma página que nós hospedamos, com seu logotipo e cores, que seu usuário sai do seu app para usar.

As duas linhas do widget são uma integração, não duas. Um único init dá a você as duas: monte frames onde quiser nossos botões e chame popup() a partir do seu próprio botão em todos os outros lugares. Elas compartilham uma sessão e reportam nos mesmos handlers.O modo direto é o mesmo popup sem o nosso script — para uma página com uma Content-Security-Policy rígida, uma página renderizada no servidor ou um app nativo. Ali você mesmo abre e observa o popup.

Adicione o script

Fixe uma versão e seu hash, ou acompanhe um canal sem hash. Nunca os dois — um atributo integrity em uma URL móvel deixa de funcionar no nosso próximo release, porque o arquivo que ela nomeia mudou legitimamente.
Pinned version
Tracking v1
v1 é o canal a recomendar. Ele recebe correções, mas nunca cruza uma breaking change. latest cruza versões major por definição, então em algum momento entregará à sua página uma versão cujo comportamento você não revisou. O hash de cada versão é publicado no manifest.json, que também nomeia o que cada canal serve atualmente:
manifest.json
Cada bundle também abre com um comentário nomeando sua própria versão, que é a forma mais rápida de nos dizer o que uma página está de fato executando:

Content-Security-Policy

Se a sua página envia uma Content-Security-Policy, ela precisa de duas entradas, ambas nomeando o host de onde você carrega o script:
Essa é a lista inteira. Você não precisa de nenhuma entrada connect-src para nós — nossos frames alcançam nossa API de dentro deles mesmos, não da sua página — e nenhuma entrada para popups, que são janelas de nível superior que a sua política não governa. As duas entradas foram medidas: remover script-src bloqueia o script, e remover frame-src bloqueia o frame.

Inicie uma instância

session é a única opção obrigatória. Ela é chamada uma vez por instância, não uma vez por mount, e deve retornar a resposta do seu backend a Criar uma Link Session com mode: "connect"{ sessionId, token, expiresAt } — exatamente como ela voltou.
Your page
Your backend
Uma sessão de widget não nomeia nenhum network — ela autoriza todas as redes que sua conta permite, e quais aparecem é decidido por mount, na sua página. Ela carrega, sim, um origin, que é a única coisa que faz os frames renderizarem: um frame compara a página que o incorpora com esse valor e se recusa a renderizar em qualquer outro lugar.
Crie a sessão no seu servidor. A chamada precisa da sua API Key, e o token que ela retorna autentica seu usuário no User Profile dele — trate-o como uma senha.
Chamamos session novamente antes de o token expirar, então o widget continua funcionando em uma página deixada aberta o dia todo. Uma chamada que rejeita, ou que não retorna token, é repetida mais duas vezes — após 0.5s e depois 1s — antes de desistirmos e emitirmos error. Então um refresh custa no máximo três chamadas ao seu endpoint.

Monte um slot

Um mount por slot. Peça uma rede, várias ou tudo o que a sessão permite — a granularidade é sua, então um slot pode ser uma única linha em uma tabela existente ou um painel contendo tudo.
mount recebe um seletor CSS ou um elemento, e retorna { unmount, element }. Ele lança uma exceção se o alvo não corresponde a nada — o que quase sempre é um slot que ainda não existe, então monte depois que seu markup estiver no documento. Cada mount é um iframe. Ele reporta sua própria altura para nós e nós o redimensionamos para corresponder, então seu layout se reorganiza conforme nosso conteúdo muda; além de maxHeight, o frame rola internamente em vez de escapar da sua página. O slot mais estreito que suportamos é 300px. As chaves de rede são as próprias da Ayrshare, e as grafias alternativas também funcionam: instagram e instagramapi significam ambas instagramApi, e x significa twitter. Uma chave que não é uma rede não renderiza tile algum.

Seu próprio botão

Um cliente que prefere usar o próprio botão em vez de um dos nossos frames chama popup em vez disso. Ele executa o mesmo fluxo, na mesma sessão, e reporta nos mesmos handlers.
Chame-o diretamente dentro do handler de clique, sem nada com await antes dele. Um navegador só permite um popup enquanto ainda está processando o clique do seu usuário, e essa permissão não sobrevive a um await. De qualquer forma nada precisa de await — a sessão foi criada no init.
popup retorna { close(), network }, e sempre retorna um handle — inclusive depois de um popup bloqueado, quando close() não faz nada — para que seu código nunca precise verificar null antes de chamar close(). Todas as redes funcionam aqui, incluindo as que um frame conclui dentro do próprio painel: o Facebook mostra sua tela explicativa de transição no popup, Bluesky e X mostram seu formulário de credenciais, e LinkedIn, Pinterest, YouTube e Google Business vão até a rede e voltam. Ele lança uma exceção de forma síncrona para as três coisas que são erros de programação — nenhum network, uma instância destruída ou uma sessão que ainda não resolveu. Um popup bloqueado não é uma delas: esse emite error com reason: "popupBlocked", porque seu usuário não fez nada de errado. No máximo um popup fica aberto por vez. Uma segunda chamada fecha o primeiro e reporta cancelled com reason: "superseded" nele. Um popup que um dos nossos frames abriu é outra coisa e nunca é tocado, então seu botão não pode cancelar um fluxo em andamento dentro de um slot montado.
Se a sessão pode vincular uma rede é a resposta do servidor, não do script. Uma sessão restrita ao Bluesky à qual se pede LinkedIn recebe uma recusa renderizada no popup e reportada como error. O script só verifica que uma rede foi nomeada.

React

O script é livre de frameworks, então o React não precisa de nada especial de nós — mas quatro coisas sobre seu ciclo de vida valem acertar de primeira. Carregue o script uma vez, fora da sua árvore de componentes. No Next.js isso é next/script no seu layout raiz; no Vite ou Create React App é uma tag no index.html. Carregá-lo por componente o executa novamente a cada mount.
ConnectAccounts.jsx
Nunca reutilize uma instância depois de destroy(). Uma instância destruída permanece destruída — popup() lança exceção nela, e mount() não a trará de volta. Crie uma nova instância na próxima execução do effect, que é o que o código acima faz.
Duas consequências desse padrão, e nenhuma delas é um bug:
  • Em desenvolvimento você verá o callback de session disparar duas vezes. O Strict Mode do React executa os effects mount → unmount → mount, então a instância é criada, destruída e criada de novo. O cleanup acima torna isso seguro; custa uma chamada extra ao seu backend em dev e nenhuma em produção.
  • Mantenha as dependências do effect estáveis. Um array literal passado direto para mount a partir do render de um pai é um valor novo a cada vez, então um effect que depende dele derruba o widget e o reconstrói a cada render. Memoize-o, ou mantenha-o constante como acima.

Eventos

Inscreva-se com on, que retorna uma função de cancelamento de inscrição. Os handlers recebem o payload do evento e o mount de onde ele veio; off(name, handler) faz o mesmo trabalho quando você prefere nomear o handler.
Dez eventos. Todos carregam um network, exceto ready e exceto o único tipo de error que não tem relação com uma rede — consulte error tem duas origens abaixo. Quatro deles são desfechossuccess, unlinked, error e cancelled — e exatamente um chega por tentativa. closed é um aviso de ciclo de vida que segue um desfecho, em vez de ser um. click dispara antes de qualquer trabalho de vinculação começar, então ele reporta um clique que um popup bloqueado ou uma sessão morta vai em seguida recusar. É o evento a usar para o seu próprio analytics; started é o que significa que uma tentativa está realmente em execução.

Motivos

error tem duas origens

Apenas uma delas é uma falha de vinculação, e elas carregam campos diferentes.
  • Um erro de vinculação carrega network, code e o mount de onde veio.
  • Um erro de sessão — não conseguimos criar ou renovar sua sessão — carrega apenas message, porque nada estava sendo vinculado naquele momento.
Desestruture defensivamente: code e network são undefined no segundo tipo.

state poupa você do polling

state é o canal de dados, e não um relato sobre uma tentativa. Cada frame emite um por rede quando é montado, carregando o estado atual daquela rede e o timestamp since desde quando ela o mantém, e outro sempre que um estado muda — incluindo mudanças que se originam do nosso lado, como um token que morre e vira relink obrigatório. Assim você pode dirigir toda a sua UI a partir do widget sem fazer polling de nada. Os valores são o mesmo enum que GET /profiles com include=state retorna: linked, unlinked, identityVerificationRequired, restricted, rateLimited, suspended.

Desvinculação

Nossos tiles desvinculam além de vincular. Seu usuário clica em uma rede conectada, confirma, e a conta é removida:
  1. click dispara com action: "unlink".
  2. unlinked dispara quando a remoção está salva.
Uma desvinculação que falha reporta error, e uma da qual seu usuário desiste na etapa de confirmação reporta cancelled. Não há um evento separado de falha de desvinculação.

Aparência

A folha de estilos de um cliente não consegue alcançar o interior de um frame cross-origin, então o estilo viaja como dados que aplicamos dentro dele. Passe appearance ao init como propriedades personalizadas de CSS; cada uma que não recebermos mantém nosso padrão.
Defina as cores em pares. Um token de fundo sem um token de primeiro plano ao lado é a única forma de fazer isso produzir algo ilegível: defina --ayr-connect-surface-bg com um valor escuro sozinho e nosso --ayr-connect-surface-fg padrão continua sendo azul-marinho escuro. Nada pode inferir a outra metade por você.
Sem nenhum appearance, todos os tokens mantêm seu padrão e um frame fica assim:
Três tiles do Ayrshare Connect com a aparência padrão

Tokens padrão: superfícies brancas, texto azul-marinho escuro, accent índigo, raio de 8px.

Passe um punhado de tokens e o mesmo frame assume a sua paleta. Este exemplo torna as superfícies azul-claras, aprofunda o texto e o accent para combinar, e arredonda um pouco mais os cantos:
Três tiles do Ayrshare Connect reestilizados com superfícies azul-claras e um accent azul mais profundo

Os mesmos três tiles depois de os tokens acima serem aplicados.

Há uma paleta e nenhum preset claro/escuro. Nada reage a prefers-color-scheme, de propósito — o tema da sua página pode não corresponder ao sistema operacional do seu usuário, e uma media query silenciosamente derrotaria as cores que você escolheu. Um dashboard escuro é tematizado fornecendo valores escuros. Esta lista de tokens é um contrato suportado que mantemos entre versões.

Os tokens

Um valor que não é CSS válido para o seu token é ignorado, com um aviso no seu console, em vez de aplicado. Isso importa mais do que parece: um 8 sem unidade para --ayr-connect-spacing é uma string perfeitamente inocente que invalidaria todo cálculo que a lê e colapsaria o layout, sem erro em lugar nenhum. Dê unidade aos comprimentos.

Seu próprio nome na tela de transição

Antes de entregarmos seu usuário a uma rede, mostramos uma tela curta nomeando por meio de quem ele está conectando. Dois ganchos permitem que você a torne sua, e ambos são estáveis entre versões. --ayr-connect-partner-name define o rótulo. É o único token cujo valor é texto, então ele precisa estar entre aspas como uma string CSS — um valor sem aspas é inválido e não renderiza nada:
O logotipo não é um token. Nós entregamos a marca como um elemento posicionado e dimensionado e você o preenche com uma background-image via css, como acima — um token que pudesse buscar uma imagem de dentro do nosso documento não é algo que aceitamos, então a requisição vem de uma regra que você escreveu em vez de um valor que você nos passou.
[data-ayr-connect-partner-mark] e [data-ayr-connect-partner-name] são a exceção à ressalva sobre CSS personalizado abaixo: esses dois seletores fazem parte do contrato e nós os mantemos entre versões.

CSS personalizado

css recebe uma string aplicada dentro de cada frame, para os casos que os tokens não cobrem.
CSS personalizado não é suportado entre versões. Seus seletores miram nosso markup interno, que muda entre releases — uma regra que funciona hoje pode silenciosamente parar de corresponder após qualquer atualização. O contrato de tokens acima é a parte que mantemos. Fixe uma versão se você depende de CSS personalizado.
Os popups herdam o appearance e o css da instância exatamente como os frames, então seu usuário não vê nossos padrões neutros aparecerem no meio de um fluxo.

Vale saber antes de lançar

Um popup que você abriu com popup() não pode ser informado do porquê de um token ter sido recusado — para dizer isso ele teria de confiar em uma origem que ainda não validou, o que nosso modelo de segurança não permite. Então um popup carregando um token morto fecha e aparece como cancelled com reason: "popupClosed" em vez de error.Na prática isso é raro: um popup aberto antes de um refresh silencioso continua funcionando, porque ele validou seu token quando abriu. Se você vê resultados popupClosed inexplicados, verifique se o seu endpoint de session está retornando uma sessão nova.
Catorze mounts compartilham um token e custam uma chamada ao seu backend, não catorze. Se você quer slots com escopos diferentes — um allowedSocial diferente em alguns deles — execute um segundo init com a própria sessão dele, em vez de esperar que um mount a restrinja.
Cada sessão carrega o origin em que a sua página roda, e um frame compara a página que o incorpora com esse valor antes de renderizar qualquer coisa. Um frame incorporado em outro lugar permanece em branco e não envia eventos. Não há allowlist para registrar nem nada para configurar — envie o origin correto ao criar a sessão.
Os frames reportam sua altura ao script, e o script os redimensiona. Seu layout simplesmente se reorganiza. Não há evento de resize para assinar, e nada para medir do seu lado.

Requisitos

  • O Max Pack. Uma sessão de widget é uma sessão em modo connect, e criar uma sem o Max Pack retorna code: 504. Entre em contato com o suporte se você precisar do modo connect habilitado em uma conta sem ele.
  • Um origin em cada sessão — a origem exata em que a sua página roda. Omiti-lo retorna code: 505; um valor que não é uma origem https, um esquema personalizado ou http://localhost retorna code: 506.
  • Nenhum network na sessão. Esse parâmetro é o que torna uma sessão modo direto, e a URL de uma sessão em modo direto não é o que o script espera.
Todos os códigos acima estão na referência de Erros de Link Session, com a mensagem exata que a API retorna e o que fazer a respeito.