> ## Documentation Index
> Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Construisez votre propre popup de liaison

> Le mode direct — connectez un réseau à la fois depuis votre propre bouton, avec une popup que vous ouvrez et surveillez vous-même.

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

<PlansAvailable plans={["business"]} maxPackRequired={true} />

Le mode direct (Direct Mode) connecte **un seul réseau social à la fois**, depuis un bouton de
votre propre tableau de bord. Vous créez une session de liaison pour ce réseau, ouvrez l'URL
qu'elle retourne dans une popup, et votre page est informée de ce qui s'est passé. Votre
utilisateur ne voit jamais de page listant tous les réseaux, et ne quitte jamais votre application
plus longtemps que ne le prend la connexion du réseau lui-même.

## Quelle surface choisir

Trois formes, et les deux premières sont la même intégration. Cette page est celle que vous
construisez vous-même.

| Surface                                                                                                                         | Votre utilisateur voit                                                                               | Marque blanche                                                                                       | Choisissez-la quand                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Widget — frames intégrées** ([mount](/docs/multiple-users/connect-widget#mount-a-slot))                                            | nos boutons directement dans votre propre mise en page ; aucune popup avant celle du réseau lui-même | **La plus forte.** Votre page, vos polices et vos couleurs, et votre utilisateur ne la quitte jamais | vous avez un tableau de bord avec une ligne par réseau et voulez que la liaison se fasse sur place. Max Pack. |
| **Widget — votre propre bouton** ([popup](/docs/multiple-users/connect-widget#your-own-button))                                      | votre bouton, puis une seule popup pour le réseau                                                    | **Forte.** La popup est la nôtre, mais elle est brève et hérite de votre apparence                   | vous voulez votre propre bouton et votre propre style, et aucune frame dans votre mise en page. Max Pack.     |
| **Page de liaison hébergée** ([mode d'emploi](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication)) | une page que nous hébergeons, portant votre logo, vos couleurs et votre CSS personnalisé             | **La plus faible.** C'est notre page, et votre utilisateur quitte la vôtre pour l'utiliser           | vous voulez un lien unique à distribuer, ou vous intégrez par e-mail. Rien à construire, pas de Max Pack.     |

<Note>
  **Le mode direct est la popup de la troisième ligne sans notre script.** Si votre page peut
  charger le script, le [widget](/docs/multiple-users/connect-widget) fait tout ce que décrit cette page
  pour vous — il ouvre et surveille la popup lui-même, et il peut aussi intégrer des frames. Le
  mode direct est ce qu'il vous faut lorsque votre page ne peut pas charger un script tiers, ou que
  la surface est une application native plutôt qu'un navigateur.
</Note>

<Frame caption="Votre bouton, votre page. La popup est la seule chose de nous que votre utilisateur voit, et seulement le temps dont le réseau a besoin.">
  <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-popup.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=b68021d477703d97a5994ee85d299be6" alt="A customer dashboard with its own Connect buttons and an Ayrshare popup showing the Facebook hand-off screen" width="2880" height="1317" data-path="images/multiple-users/connect-widget-popup.webp" />
</Frame>

## Ce que vous construisez

Quatre étapes. La première est sur votre serveur, les autres dans votre page.

<Steps>
  <Step title="Créez une session pour un réseau">
    Depuis votre backend, appelez
    [Créer une session de liaison](/docs/apis/profiles/create-link-session) avec `mode: "connect"`, le
    `network`, et l'`origin` sur laquelle votre page s'exécute.

    ```javascript Your backend theme={"system"}
    const response = await fetch("https://api.ayrshare.com/api/profiles/link-sessions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.AYRSHARE_API_KEY}`,
        "Profile-Key": profileKey,
      },
      body: JSON.stringify({
        mode: "connect",
        network: "reddit",
        origin: "https://app.example.com",
      }),
    });

    const { url } = await response.json();
    ```

    Vous recevez en retour une `url` pointant vers une page de connexion mono-réseau, et aucun
    `token` — le token est à l'intérieur de l'URL. Traitez l'URL entière comme un mot de passe :
    elle connecte votre utilisateur à son User Profile.

    <Warning>
      Créez la session sur votre serveur, jamais dans le navigateur. L'appel nécessite votre clé API.
    </Warning>
  </Step>

  <Step title="Ouvrez-la dans le gestionnaire de clic, de manière synchrone">
    La popup doit être ouverte par `window.open` **dans le gestionnaire de clic lui-même**. Un
    navigateur n'autorise une popup que tant qu'il est encore en train de traiter le clic de votre
    utilisateur, et cette autorisation ne survit pas à un `await` — donc récupérer d'abord l'URL et
    l'ouvrir dans le callback est systématiquement bloqué par le bloqueur de popups.

    Récupérez l'URL au moment où vous affichez le bouton, ou lorsque votre utilisateur le survole.
    Au moment du clic, vous devriez déjà l'avoir.

    ```javascript Your page theme={"system"}
    // `url` a été récupérée plus tôt. Rien d'asynchrone entre le clic et window.open.
    button.addEventListener("click", () => {
      const popup = window.open(url, "ayrshare-connect", "width=600,height=800");
      if (!popup) {
        showError("Allow popups for this site to connect an account.");
        return;
      }
      listenForOutcome(popup, url);
    });
    ```
  </Step>

  <Step title="Écoutez le résultat">
    Parce que vous avez passé `origin`, la popup poste un événement à votre page pour chaque chose
    qui s'y produit : `connect:success`, `connect:error`, `connect:cancelled`, et des événements de
    progression entre les deux. Exactement l'un de ces trois arrive par connexion.

    [Événements de fin de liaison](/docs/multiple-users/link-completion-events) contient le tableau
    complet des événements et un listener à copier-coller — `listenForOutcome` ci-dessus est ce
    snippet. Deux parties de celui-ci sont faciles à omettre et toutes deux causent de vrais bugs :

    * **Vérifiez `event.origin`** par rapport à l'origine de l'URL que vous avez ouverte. N'importe
      quelle page peut poster un message à votre fenêtre, et l'origine est la seule partie d'un
      message qui ne peut pas être falsifiée.
    * **Pollez `popup.closed`**, avec une courte fenêtre de grâce avant de conclure quoi que ce
      soit. Une popup que votre utilisateur a fermée à la main n'envoie rien du tout, et sans la
      fenêtre de grâce une connexion réussie peut être rapportée comme annulée.
  </Step>

  <Step title="Gérez chaque fin">
    | Fin                 | Ce qu'elle signifie                                                                                | Que faire                                                                                                           |
    | ------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
    | `connect:success`   | le compte est connecté **et enregistré**                                                           | rafraîchissez cette ligne. Un [`GET /user`](/docs/apis/user/profile-details) juste après l'affiche déjà.                 |
    | `connect:error`     | la connexion a échoué                                                                              | affichez `message`. `code` est présent lorsque l'échec a un code catalogué et absent lorsqu'il n'en a pas.          |
    | `connect:cancelled` | votre utilisateur a renoncé, ou a fermé la fenêtre                                                 | laissez la ligne telle quelle. `reason` est `popupClosed`, `scopesDenied` ou `userCancelled`.                       |
    | rien n'arrive       | le lien était expiré, révoqué ou inconnu, donc la page n'a jamais appris où envoyer les événements | pollez [Obtenir une session de liaison](/docs/apis/profiles/get-link-session), qui rapporte ces états de manière fiable. |
  </Step>
</Steps>

<Tip>
  Ajoutez `&autoClose=false` à l'URL pendant que vous construisez. La popup reste alors ouverte
  après chaque résultat au lieu de se fermer d'elle-même, pour que vous puissiez lire ce qu'elle
  affiche.
</Tip>

## Notes par réseau

La plupart des réseaux, c'est une popup et rien d'autre : votre utilisateur clique, autorise auprès
du réseau, et la popup se ferme. Voici les exceptions à connaître avant de construire.

<AccordionGroup>
  <Accordion title="X nécessite vos propres clés API">
    X en mode direct utilise **vos** identifiants X Developer App, fournis à la création de la
    session via les en-têtes `X-Twitter-OAuth1-Api-Key` et `X-Twitter-OAuth1-Api-Secret` sur
    [Créer une session de liaison](/docs/apis/profiles/create-link-session).

    Une session créée pour `twitter` ou `x` **sans** ces en-têtes est refusée à l'ouverture de la
    popup : votre utilisateur est informé que la connexion n'est pas disponible et ne voit aucun
    formulaire, et votre page reçoit `connect:error` avec un `message` et **aucun `code`**. C'est
    délibéré. L'identifiant manquant est le vôtre, pas celui de votre utilisateur, et les
    utilisateurs finaux ne doivent jamais avoir à saisir vos clés API.

    Comparez avec Bluesky, où le mot de passe d'application est l'identifiant propre de
    l'utilisateur final — celui-là, la page de connexion le collecte bien, dans un formulaire à
    l'intérieur de la popup.
  </Accordion>

  <Accordion title="Facebook affiche un bouton avant la connexion de Meta">
    `network: "facebook"` affiche un unique bouton dans la popup, et la connexion propre de Meta
    s'ouvre à partir de ce clic — Meta exige que sa connexion soit lancée par un clic à l'intérieur
    de la page qui héberge son SDK. Votre utilisateur clique deux fois plutôt qu'une ; rien d'autre
    ne diffère.

    Instagram se comporte de la même manière lorsqu'il est lié **via une page Facebook** — c'est-à-dire
    lorsque la session porte `instagramLinkMethod: "facebook"`, ou lorsque le paramètre
    [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) de votre compte
    sélectionne ce flux. Avec Instagram Login direct, il n'y a pas de bouton supplémentaire.
  </Accordion>

  <Accordion title="Bluesky et Telegram affichent du contenu de page, pas une redirection">
    Aucun des deux n'envoie votre utilisateur vers la connexion d'un réseau. La popup affiche du
    contenu à la place : un formulaire de handle et de mot de passe d'application pour Bluesky, et
    un code à utiliser pour Telegram. Les événements de résultat sont les mêmes dans les deux cas.

    X n'appartient pas à ce groupe. Avec vos clés sur la session, il se termine sans rien demander
    à votre utilisateur, et sans elles il est refusé — voir ci-dessus.
  </Accordion>

  <Accordion title="Telegram se termine hors bande">
    Telegram affiche un code plutôt que de rediriger où que ce soit, et la connexion se termine
    lorsque votre utilisateur utilise ce code — après la disparition de la popup. Il n'y a aucun
    événement navigateur à attendre, donc pollez
    [Obtenir une session de liaison](/docs/apis/profiles/get-link-session) et surveillez
    `completedNetworks`.
  </Accordion>

  <Accordion title="Les groupes Facebook ne peuvent pas être connectés de cette manière">
    Facebook Groups n'est pas une cible de liaison, donc `network: "fbg"` retourne `code: 508`
    lorsque vous créez la session.

    WhatsApp **est** disponible en mode direct. Il ouvre l'Embedded Signup de Meta dans la popup,
    et les événements de résultat sont les mêmes que pour tout autre réseau.
  </Accordion>
</AccordionGroup>

## Applications natives

Une application native ouvre la même `url`, dans le **navigateur système**, et découvre le résultat
en pollant [Obtenir une session de liaison](/docs/apis/profiles/get-link-session). Définissez `origin`
sur votre schéma personnalisé (`myapp://connected`) pour que la page ait un moyen de revenir dans
votre application ; un schéma personnalisé ne peut pas recevoir d'événements, car il n'y a pas de
fenêtre de navigateur à laquelle les poster.

* **iOS** — `ASWebAuthenticationSession`, ou `SFSafariViewController`.
* **Android** — Chrome Custom Tabs.

<Warning>
  **N'ouvrez jamais une URL de liaison dans une webview intégrée** (`WKWebView`, `UIWebView`,
  `WebView` Android). Les réseaux sociaux refusent de s'y authentifier : Google rejette la
  connexion avec `disallowed_useragent`, et Meta la bloque purement et simplement. Votre
  utilisateur voit la page d'erreur du réseau lui-même, pas la nôtre, et rien de ce que vous pouvez
  changer de votre côté n'y remédie. Les composants de navigateur système ci-dessus existent
  exactement pour cette raison et gardent l'utilisateur dans votre application.
</Warning>

## Ce que le mode direct nécessite

<ul className="custom-bullets">
  <li>
    Le **[Max Pack](/docs/additional/maxpack)**. Créer une session en mode connect sans lui retourne
    `code: 504`, quoi que dise le reste de la requête.
  </li>

  <li>
    Un **`origin`** sur chaque session. Il n'y a pas d'allowlist ni d'étape d'enregistrement — vous
    l'envoyez à chaque appel. L'omettre retourne `code: 505` ; une valeur qui n'est pas une origine
    `https`, un schéma personnalisé ou `http://localhost` retourne `code: 506`.
  </li>

  <li>
    Un **`network`** que votre compte a activé. Un nom non reconnu retourne `code: 508` ; un nom
    reconnu que votre compte n'a pas activé retourne `code: 509`, ce que vous pouvez corriger sur
    votre page [Réseaux sociaux](/docs/multiple-users/manage-user-profiles#set-social-networks-access).
  </li>

  <li>
    **Pas** d'`allowedSocial`. Il ne peut pas être combiné avec `network` (`code: 507`) — une
    session mono-réseau est déjà sa propre allowlist.
  </li>
</ul>

Chacun de ces codes figure dans la référence
[Erreurs de session de liaison](/docs/errors/errors-ayrshare#link-session-errors), avec le message
retourné par l'API.

## Étapes suivantes

<Card title="Événements de fin de liaison" icon="tower-broadcast" href="/docs/multiple-users/link-completion-events" horizontal>
  Tous les événements que la popup envoie, et le listener pour les recevoir.
</Card>

## Voir aussi

<Card title="Créer une session de liaison" icon="link" href="/docs/apis/profiles/create-link-session#connect-mode" horizontal>
  Les paramètres `mode`, `origin` et `network`, et les formes de réponse.
</Card>

<Card title="Obtenir une session de liaison" icon="magnifying-glass" href="/docs/apis/profiles/get-link-session" horizontal>
  Pollez la fin de liaison lorsque vous ne pouvez pas utiliser de popup.
</Card>
