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

# The linking flow

> How to integrate the Almedia SDK — synced from the source repository.

```
Player taps LinkButton, or your code calls ShowLink()
        │  (both open the LinkPopup)
        ▼
LinkPopup appears
        │
        ▼
Player taps CTA
        │  (LinkPopup's CTA button starts linking)
        ▼
Linking page opens (Freecash)
        │
        ▼
Player completes linking on linking page
        │
        ▼
Linking page closes; SDK syncs state (Status → Linked via OnStatusChanged)
        │
        ▼
OnScreenDismissed(Linking) fires - resume your game
        │
        ▼
OnLinkCompleted(linkedAt) fires - fresh-link celebration UX
```

The bundled flow is fully wired: `LinkButton` opens `LinkPopup`, and the popup's CTA starts linking. Host code only needs to drop a `LinkButton` prefab into a Canvas. To start the flow from your own button, see the next section.

## Trigger linking programmatically

Call `ShowLink()` to start linking from your own button. It shows the link popup, and the popup's button starts linking. The popup reports the same analytics as when the `LinkButton` opens it.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
myLinkButton.onClick.AddListener(() => Almedia.ShowLink());
```

To say where the popup opens from, pass a source. Your own popup reads it as `Source`, and the popup's events report it:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
Almedia.ShowLink(new AlmediaLinkSource("shop"));
Almedia.ShowLink(new AlmediaLinkSource("level_end", payload: new LevelEnd(level)));
```

`source.Kind` tells a `LinkButton` tap from a `ShowLink` call, whatever the name. See [`AlmediaLinkSource`](https://docs.almedia.dev/technical/api-reference/almedia/models#almedialinksource).

`ShowLink()` does nothing unless the status is `Eligible`, and nothing while a link popup is already open. Show your button only while the player can link:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
private void Awake()
{
    Almedia.OnStatusChanged += OnStatus;
    OnStatus(Almedia.Status);  // late-mount recovery
}

private void OnDestroy() => Almedia.OnStatusChanged -= OnStatus;

private void OnStatus(AlmediaStatus status) =>
    myLinkButton.gameObject.SetActive(status is AlmediaStatus.Eligible);
```

The popup comes from **Almedia → Settings → Default UI Prefabs → Link Popup**. The settings asset the SDK creates on first import has the bundled popup there. An existing settings asset keeps the slot empty after the upgrade. Until you assign a popup there, `ShowLink()` shows the popup assigned to the deprecated `LinkPopupOverride`, or else starts linking directly and logs a warning through `OnLog` once. A popup assigned in the slot ships in every build. Clear the slot if you never call `ShowLink()`.

### Your own popup design

To give the popup your own look, create a Prefab Variant of `LinkPopup` (see [Level 2 - Prefab Variants](https://docs.almedia.dev/technical/integration-guide/customize-the-ui.md#level-2-prefab-variants)), assign it to the **Link Popup** slot, and call `ShowLink()`.

For a popup built from scratch, derive from `AlmediaLinkPopupController` on your own hierarchy:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
using AlmediaSDK;
using UnityEngine;
using UnityEngine.UI;

public class MyLinkPopup : AlmediaLinkPopupController
{
    [SerializeField] private GameObject _panel;
    [SerializeField] private Button _linkButton;
    [SerializeField] private Button _closeButton;

    private void Awake()
    {
        _linkButton.onClick.AddListener(StartLinking);
        _closeButton.onClick.AddListener(Dismiss);
        _panel.SetActive(false);
    }

    protected override void ShowPopup() => _panel.SetActive(true);

    protected override void HidePopup() => _panel.SetActive(false);
}
```

Assign the prefab to the **Link Popup** slot, or to a `LinkButton`'s **Link Popup** field. The SDK instantiates it once as a root object, keeps it across scenes, and calls `ShowPopup` on every `ShowLink()`. Put a Canvas on the prefab's root object. `StartLinking` records the tap and starts linking; `Dismiss` records the close and hides the popup. Both do nothing while the popup is not open. `Source` says what opened the popup. The popup hides while the linking screen is open, comes back if the player cancels it, and closes when linking completes or the player can no longer link. The events on `AlmediaLinkPopupController` report every popup built on it; see the [API reference](https://docs.almedia.dev/technical/api-reference/almedia/ui-components.md#almedialinkpopupcontroller). Code in an assembly definition references `AlmediaLink` for the base class and `AlmediaSDK` for `AlmediaLinkSource`.

## `OnLinkCompleted`

`OnLinkCompleted` fires **only when the player completes linking during the current session**. Players who were already linked at `Initialize` time receive a `Linked` status via `OnStatusChanged` instead. This event therefore distinguishes "they just linked, right now" from "they were already linked at launch".

Use it for fresh-link UX: a celebration toast, a one-time analytics event, unlocking a tutorial step - anything that should fire only on the transition itself. The argument is the backend's ISO-8601 timestamp of the linking event.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
Almedia.OnLinkCompleted += linkedAt =>
{
    ShowThanksForLinkingToast();
    Analytics.Track("link_succeeded", new { linkedAt });
};
```

For a basic "is the player linked right now?" check - for example, to enable a menu item or update UI affordances - use `OnStatusChanged` and react when status reaches `Linked`. That fires for both fresh links and already-linked sessions.

If linking fails or the player closes the linking page, `OnErrorOccurred` may fire with `AlmediaErrorCode.LinkingFailed`. Status stays `Eligible` so the player can try again.

***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.