---
title: "Afficher un paywall ciblé AA au premier lancement dans Flutter SDK"
description: "Attendez brièvement l'attribution Apple Ads avant d'afficher le paywall au premier lancement dans Flutter, avec repli sur l'audience par défaut en cas de délai dépassé. Utilise AdaptyProfile.appliedAttributionSources."
---

L'attribution Apple Ads (AA) arrive de manière asynchrone après `Adapty().activate()`. Au premier lancement, elle n'est généralement pas encore disponible, donc si vous appelez `getPaywall` immédiatement, Adapty résout la requête par rapport à l'audience par défaut et les utilisateurs Apple Ads ratent votre paywall segmenté AA. Plutôt que d'afficher un paywall puis de le remplacer, attendez brièvement l'attribution AA avant d'afficher quoi que ce soit : affichez le paywall ciblé si l'attribution arrive dans un court délai, ou le paywall de l'audience par défaut si ce n'est pas le cas. `AdaptyProfile.appliedAttributionSources` vous indique quand l'attribution AA a été appliquée.

## Avant de commencer \{#before-you-start\}

Vous avez besoin de :
- Adapty Flutter SDK **3.17.0** ou version ultérieure.
- Apple Ads configuré pour l'application dans Adapty. Voir [Apple Ads](apple-search-ads).

## Fonctionnement \{#how-it-works\}

Après `Adapty().activate()`, le SDK demande l'attribution Apple Ads à Apple en arrière-plan et transmet le résultat au backend d'Adapty. Quand AA devient la source d'attribution active pour le profil, le SDK envoie un `AdaptyProfile` mis à jour à votre listener `didUpdateProfileStream`, avec `AdaptyAttributionSource.appleAds` dans sa liste `appliedAttributionSources`.

Au premier lancement, deux cas sont à gérer :

1. **L'attribution arrive dans le délai imparti.** Appelez `getPaywall` — Adapty résout la requête par rapport à l'audience Apple Ads et retourne le paywall ciblé.
2. **Le délai expire en premier.** Affichez plutôt le paywall de l'audience par défaut, afin que les utilisateurs sans attribution Apple Ads n'attendent pas indéfiniment. `getPaywallForDefaultAudience` le retourne sans attendre la segmentation.

`appliedAttributionSources` peut être vide. Cela signifie soit :

- L'attribution Apple Ads n'a pas encore été traitée pour ce profil, ou
- aucune attribution n'est arrivée du tout.

Dans tous les cas, `getPaywallForDefaultAudience` peut être appelé en toute sécurité — il retourne le paywall de l'audience par défaut quel que soit l'état du profil.

:::important
L'attente ne s'applique qu'au premier lancement. Une fois l'attribution Apple Ads enregistrée, elle est stockée définitivement sur le profil. À chaque lancement suivant, le profil en cache contient déjà `AdaptyAttributionSource.appleAds` dans `appliedAttributionSources`, donc le chemin d'attribution se résout immédiatement et `getPaywall` retourne le paywall segmenté Apple Ads sans aucun délai.
:::

## Implémentation \{#implementation\}

Au premier lancement, attendez `AdaptyAttributionSource.appleAds` et appliquez un délai strict — si l'attribution Apple Ads n'arrive jamais, ces utilisateurs doivent quand même voir un paywall.

1. **Activez le SDK.** Voir [Installer et configurer le Flutter SDK](sdk-installation-flutter).
2. **Abonnez-vous aux mises à jour du profil** avec `Adapty().didUpdateProfileStream.listen(…)`. Si vous n'avez pas encore configuré le listener, voir [Écouter les mises à jour d'abonnement](flutter-check-subscription-status#listen-to-subscription-updates).
3. **Surveillez `AdaptyAttributionSource.appleAds` dans `appliedAttributionSources`.** Quand il apparaît, chargez le paywall avec `getPaywall` — Adapty retourne la variante segmentée AA :

```dart
final subscription = Adapty().didUpdateProfileStream.listen((profile) async {
  if (!profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) return;
  final paywall = await Adapty().getPaywall(placementId: placementId);
  // present the segmented paywall, then cancel the subscription and the timer
});
```

   `didUpdateProfileStream` est un broadcast stream et ne rejoue pas les événements passés, donc vérifiez aussi le profil actuel une fois avec `getProfile()`. Lors des relances, l'attribution stockée est déjà appliquée et ne sera pas renvoyée.

4. **Démarrez un timer de 3 à 5 secondes en parallèle de l'abonnement.** Si le timer se déclenche avant que `AdaptyAttributionSource.appleAds` n'apparaisse, chargez plutôt le paywall de l'audience par défaut avec `getPaywallForDefaultAudience`. Affichez le premier paywall résolu et annulez l'autre chemin, afin que le paywall ne soit pas récupéré deux fois. Configurez un [paywall de secours](flutter-use-fallback-paywalls) pour le placement afin que l'utilisateur ne soit jamais bloqué en cas d'échec réseau.

## Exemple complet \{#complete-example\}

L'implémentation ci-dessous met en compétition l'attribution et un délai, précharge le paywall de l'audience par défaut en parallèle, et retourne le paywall approprié. L'appelant attend une seule fonction — aucun listener ni indicateur d'état à gérer côté appelant :

- Si l'attribution arrive dans le `timeout`, elle retourne le paywall segmenté via `getPaywall`.
- Si le `timeout` expire en premier, elle retourne le paywall de l'audience par défaut préchargé via `getPaywallForDefaultAudience`.

```dart title="apple_ads_paywall.dart"

/// Returns the Apple Ads-segmented paywall if attribution is applied within
/// [timeout], otherwise the default-audience paywall. Call after Adapty().activate().
Future<AdaptyPaywall> getPaywallOrDefault({
  required String placementId,
  required Duration timeout,
}) {
  // Prefetch the default-audience paywall right away so the timeout path resolves
  // without an extra network round-trip. `getPaywallForDefaultAudience` skips the
  // wait for segmentation data. `..ignore()` keeps an unused prefetch from surfacing
  // as an unhandled error; the error still reaches the caller if this paywall wins.
  final defaultPaywall =
      Adapty().getPaywallForDefaultAudience(placementId: placementId)..ignore();

  final completer = Completer<AdaptyPaywall>();
  late final StreamSubscription<AdaptyProfile> subscription;
  late final Timer timer;

  void resolve(Future<AdaptyPaywall> paywall) {
    if (completer.isCompleted) return;
    timer.cancel();
    subscription.cancel();
    completer.complete(paywall);
  }

  void onProfile(AdaptyProfile profile) {
    if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) {
      resolve(Adapty().getPaywall(placementId: placementId));
    }
  }

  // Attribution path: react to profile updates as attribution is applied.
  subscription = Adapty().didUpdateProfileStream.listen(onProfile);

  // The stream is a broadcast stream and doesn't replay, so check the current
  // profile too — on relaunches attribution is already stored and won't re-emit.
  Adapty().getProfile().then(onProfile).ignore();

  // Timeout path: fall back to the prefetched default-audience paywall.
  timer = Timer(timeout, () => resolve(defaultPaywall));

  return completer.future;
}
```

Appelez depuis votre écran de démarrage, puis affichez le paywall une fois qu'il est résolu :

```dart
try {
  final paywall = await getPaywallOrDefault(
    placementId: 'YOUR_PLACEMENT_ID',
    timeout: const Duration(seconds: 5),
  );
  // present the paywall
} on AdaptyError catch (adaptyError) {
  // handle the error or show a fallback paywall
} catch (e) {
  // handle the error
}
```

Ajustez `timeout` selon le temps que vous êtes prêt à faire attendre les utilisateurs avant qu'un paywall n'apparaisse. La plupart des utilisateurs n'ont pas d'attribution Apple Ads, donc ils attendent le délai complet — 3 à 5 secondes est un équilibre raisonnable. L'attribution qui arrive le fait généralement dans les quelques secondes suivant le lancement.

Si votre application écoute déjà `didUpdateProfileStream` à d'autres fins (par exemple, [vérifier l'état de l'abonnement](flutter-check-subscription-status#listen-to-subscription-updates)), vous n'avez pas besoin de le modifier. `didUpdateProfileStream` est un broadcast stream, donc il prend en charge plusieurs listeners indépendants sans affecter les autres.