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

# Trigger components quickstart

> Add a Gifts Button and a Claim Reminder to your app on iOS, Android, React Native, Flutter, or the web.

This page adds both trigger components to your app in a few lines each: a [Gifts Button](/publishers/triggers/gifts-button) at a reward moment and a [Claim Reminder](/publishers/triggers/claim-reminder) on a screen users come back to. Read [Trigger components](/publishers/triggers/overview) first if you want the picture before the code.

<Info>
  **Requires SDK 2.4.0+** on every platform. See [Minimum SDK versions](/publishers/triggers/overview#minimum-sdk-versions).
</Info>

## Before you start

* Install the Encore SDK 2.4.0 or later for your platform and call `configure()`, as in its quickstart: [iOS](/publishers/ios/quickstart/install), [Android](/publishers/android/quickstart/install), [React Native](/publishers/react-native/quickstart/install), [Flutter](/publishers/flutter/quickstart/install), or [Web](/publishers/web/quickstart/install).
* Identify your user with `identify()` once you know who they are, as for `show()`.
* Pick a placement ID for each spot, such as `milestone_reached` for the end of a streak and `home` for your home screen. A trigger component opens the same reward sheet `show()` presents at that placement, so the placement works exactly as it does there.

A trigger component only appears when the reward sheet it opens has offers for this user. Until then it takes up no space, so you can add it to a screen and ship it before anything shows.

## Add a Gifts Button

Put it on the screen where you would otherwise call `show()` for a reward, in place of that call:

<CodeGroup>
  ```swift iOS (SwiftUI) theme={null}
  import Encore
  import SwiftUI

  struct StreakDoneView: View {
      var body: some View {
          VStack(spacing: 16) {
              Text("7 day streak")
              GiftsButton(placement: "milestone_reached")
          }
          .padding()
      }
  }
  ```

  ```swift iOS (UIKit) theme={null}
  import Encore
  import UIKit

  final class StreakDoneViewController: UIViewController {
      override func viewDidLoad() {
          super.viewDidLoad()
          let stack = UIStackView()
          stack.axis = .vertical
          stack.spacing = 16
          stack.translatesAutoresizingMaskIntoConstraints = false
          view.addSubview(stack)
          NSLayoutConstraint.activate([
              stack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
              stack.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
              stack.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
          ])
          stack.addArrangedSubview(GiftsButtonView(placement: "milestone_reached"))
      }
  }
  ```

  ```kotlin Android (Compose) theme={null}
  import androidx.compose.foundation.layout.Arrangement
  import androidx.compose.foundation.layout.Column
  import androidx.compose.material3.Text
  import androidx.compose.runtime.Composable
  import androidx.compose.ui.unit.dp
  import com.encorekit.encore.GiftsButton

  @Composable
  fun StreakDoneScreen() {
      Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
          Text("7 day streak")
          GiftsButton(placement = "milestone_reached")
      }
  }
  ```

  ```xml Android (XML layout) theme={null}
  <com.encorekit.encore.GiftsButtonView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:encorePlacement="milestone_reached" />
  ```

  ```tsx React Native theme={null}
  import { View, Text } from 'react-native';
  import { EncoreGiftsButton } from '@encorekit/react-native';

  export function StreakDoneScreen() {
    return (
      <View>
        <Text>7 day streak</Text>
        <EncoreGiftsButton placement="milestone_reached" />
      </View>
    );
  }
  ```

  ```dart Flutter theme={null}
  import 'package:flutter/material.dart';
  import 'package:encore_flutter/encore_flutter.dart';

  class StreakDoneScreen extends StatelessWidget {
    const StreakDoneScreen({super.key});

    @override
    Widget build(BuildContext context) {
      return Column(
        children: const [
          Text('7 day streak'),
          EncoreGiftsButton(placement: 'milestone_reached'),
        ],
      );
    }
  }
  ```

  ```javascript Web SDK theme={null}
  import Encore from '@encorekit/web-sdk';

  // Call configure() first, as in the Web quickstart.
  const giftsButton = Encore.triggers.giftsButton.mount(
    document.getElementById('streak-gift'),
    { placement: 'milestone_reached' }
  );

  // When you remove the element from the page:
  // giftsButton.unmount();
  ```

  ```tsx Web SDK (React) theme={null}
  import { GiftsButton } from '@encorekit/web-sdk/react';

  // Render inside your EncoreProvider.
  export function StreakDone() {
    return (
      <section>
        <h2>7 day streak</h2>
        <GiftsButton placement="milestone_reached" />
      </section>
    );
  }
  ```
</CodeGroup>

That's the whole setup. Encore picks the look, the copy, and the colors, and can change them without an app update. A tap opens the reward sheet for that placement.

## Add a Claim Reminder

Put it on a screen users return to on their own, such as your home screen:

<CodeGroup>
  ```swift iOS (SwiftUI) theme={null}
  import Encore
  import SwiftUI

  struct HomeView: View {
      var body: some View {
          ScrollView {
              VStack(spacing: 16) {
                  ClaimReminder(placement: "home")
                  // The rest of your home screen.
              }
              .padding()
          }
      }
  }
  ```

  ```swift iOS (UIKit) theme={null}
  // In your view controller, next to your other arranged subviews.
  stack.addArrangedSubview(ClaimReminderView(placement: "home"))
  ```

  ```kotlin Android (Compose) theme={null}
  import androidx.compose.foundation.layout.Column
  import androidx.compose.runtime.Composable
  import com.encorekit.encore.ClaimReminder

  @Composable
  fun HomeScreen() {
      Column {
          ClaimReminder(placement = "home")
          // The rest of your home screen.
      }
  }
  ```

  ```xml Android (XML layout) theme={null}
  <com.encorekit.encore.ClaimReminderView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:encorePlacement="home" />
  ```

  ```tsx React Native theme={null}
  import { ScrollView } from 'react-native';
  import { EncoreClaimReminder } from '@encorekit/react-native';

  export function HomeScreen() {
    return (
      <ScrollView>
        <EncoreClaimReminder placement="home" />
        {/* The rest of your home screen. */}
      </ScrollView>
    );
  }
  ```

  ```dart Flutter theme={null}
  import 'package:flutter/material.dart';
  import 'package:encore_flutter/encore_flutter.dart';

  class HomeScreen extends StatelessWidget {
    const HomeScreen({super.key});

    @override
    Widget build(BuildContext context) {
      return ListView(
        children: const [
          EncoreClaimReminder(placement: 'home'),
          // The rest of your home screen.
        ],
      );
    }
  }
  ```

  ```javascript Web SDK theme={null}
  import Encore from '@encorekit/web-sdk';

  const reminder = Encore.triggers.claimReminder.mount(
    document.getElementById('claim-reminder'),
    { placement: 'home' }
  );
  ```

  ```tsx Web SDK (React) theme={null}
  import { ClaimReminder } from '@encorekit/web-sdk/react';

  export function Home() {
    return (
      <main>
        <ClaimReminder placement="home" />
        {/* The rest of your home screen. */}
      </main>
    );
  }
  ```
</CodeGroup>

<Note>
  Claim Reminder shows a claim the user started but hasn't finished. Until the SDKs can read the user's open claims from Encore, which ships after the first trigger release, it shows only claims made in your app on this device. Adding it now is safe: with no claim to show, it takes no space and sends nothing.
</Note>

## Use your own words (optional)

Set the entry's text with `headline`, `subheadline` and `cta`, as you do for the reward sheet. Leave any of them out and that line keeps the look's own copy, in the user's language:

<CodeGroup>
  ```swift iOS theme={null}
  GiftsButton(placement: "milestone_reached")
      .headline("Level complete!")
      .cta("Claim")
  ```

  ```kotlin Android theme={null}
  GiftsButton(placement = "milestone_reached", headline = "Level complete!", cta = "Claim")
  ```

  ```tsx React Native theme={null}
  <EncoreGiftsButton placement="milestone_reached" headline="Level complete!" cta="Claim" />
  ```

  ```dart Flutter theme={null}
  EncoreGiftsButton(placement: 'milestone_reached', headline: 'Level complete!', cta: 'Claim')
  ```

  ```javascript Web SDK theme={null}
  Encore.triggers.giftsButton.mount(element, { placement: 'milestone_reached', headline: 'Level complete!', cta: 'Claim' });
  ```

  ```tsx Web SDK (React) theme={null}
  <GiftsButton placement="milestone_reached" headline="Level complete!" cta="Claim" />
  ```
</CodeGroup>

Claim Reminder takes the same options. [Your text](/publishers/triggers/overview#your-text) says which looks show which line.

## Pay your prize (optional)

If your app pays its own prize for trying an offer, pass it as `publisherReward` and read the result in `onResult`. See [Pass your prize and read the result](/publishers/triggers/gifts-button#pass-your-prize-and-read-the-result).

## The trigger host

Each shorthand on this page is the trigger host with its ID built in. Use the host when your app places trigger components through one code path, for example from your own server-driven layout. It takes the trigger ID as a string:

<CodeGroup>
  ```swift iOS (SwiftUI) theme={null}
  EncoreTrigger("giftsButton", placement: "milestone_reached")
  ```

  ```swift iOS (UIKit) theme={null}
  let trigger = EncoreTriggerView(id: "giftsButton", placement: "milestone_reached")
  ```

  ```kotlin Android (Compose) theme={null}
  EncoreTrigger(id = "giftsButton", placement = "milestone_reached")
  ```

  ```kotlin Android (View) theme={null}
  val trigger = EncoreTriggerView(context = this, id = "giftsButton", placement = "milestone_reached")
  ```

  ```xml Android (XML layout) theme={null}
  <com.encorekit.encore.EncoreTriggerView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:encoreTriggerId="giftsButton"
      app:encorePlacement="milestone_reached" />
  ```

  ```tsx React Native theme={null}
  <EncoreTrigger id="giftsButton" placement="milestone_reached" />
  ```

  ```dart Flutter theme={null}
  EncoreTrigger(id: 'giftsButton', placement: 'milestone_reached')
  ```

  ```javascript Web SDK theme={null}
  const handle = Encore.triggers.mount('giftsButton', element, { placement: 'milestone_reached' });
  ```

  ```tsx Web SDK (React) theme={null}
  <EncoreTrigger id="giftsButton" placement="milestone_reached" />
  ```
</CodeGroup>

An ID the SDK doesn't know renders nothing, so a server that names a future trigger component can't break an older app.

## Parameters

The host and every shorthand take these by name. Every one except `placement` (and `id` on the host) is optional.

| Parameter | Default | Meaning |
| - | - | - |
| `id` | Built into each shorthand | Host only. The trigger ID: `giftsButton` or `claimReminder` |
| `placement` | Required | The placement ID for this spot, as for `show()` |
| `useCase` | The reward use case | The use case of the sheet it opens. Only the reward use case is supported today; the churn use case renders nothing |
| `autoOpen` | None | Gifts Button and the host only. When an Encore test calls for it, the sheet can open by itself: at most once a day at each placement, in the foreground, never over another Encore sheet. Set it to off to stop that |
| `icon` | `gift` | The icon the look draws: `gift`, `appIcon`, or `none`. See [Icon](/publishers/triggers/overview#icon) |
| `alignment` | `center` | Where it sits when its container is wider than its look: `leading`, `center` or `trailing`, in your app's writing direction. Changing it only moves it. See [Width and alignment](/publishers/triggers/overview#width-and-alignment) |
| `appearance` | None | Your colors and `colorScheme` for the trigger component only, never the sheet it opens. See [Colors](/publishers/triggers/overview#colors) |
| `publisherReward` | None | Your prize for trying an offer, handed to every sheet it opens |
| `onResult` | None | Called once per sheet it opens, after the sheet closes, with that sheet's result |
| `headline`, `subheadline`, `cta` | The look's own copy | Your words for the entry's main line, second line, and button. Blank falls back to the look's copy. On iOS they're modifiers: `.headline("…")`. See [Your text](/publishers/triggers/overview#your-text) |

The names of the typed values differ by platform:

| | iOS | Android | React Native | Flutter | Web |
| - | - | - | - | - | - |
| Use case | `UseCase.rewardUsers` | `UseCase.REWARD_USERS` (XML `reward`) | `UseCase.rewardUsers` | `EncoreUseCase.rewardUsers` | `'rewardUsers'` |
| `autoOpen` | `.off` | `AutoOpen.OFF` (XML `off`) | `AutoOpen.off` | `EncoreAutoOpen.off` | `'off'` |
| `icon` | `TriggerIcon.appIcon` | `TriggerIcon.APP_ICON` | `TriggerIcon.appIcon` | `EncoreTriggerIcon.appIcon` | `'appIcon'` |
| `alignment` | `EncoreAlignment.leading` | `EncoreAlignment.LEADING` (XML `leading`) | `EncoreAlignment.leading` | `EncoreAlignment.leading` | `'leading'` |
| `appearance.colorScheme` | `AppearanceConfig.ColorScheme.dark` | `AppearanceConfig.ColorScheme.DARK` | `'dark'` | `EncoreColorScheme.dark` | `'dark'` |
| Prize | `PublisherReward` | `PublisherReward` | `PublisherReward` | `EncorePublisherReward` | `PublisherReward` |
| `onResult` gets | `PresentationResult` | `PresentationResult` | `PresentationResult` | `EncorePresentationResult` | `ShowResult` |

On the web, `publisherReward`, `onResult` and `alignment` go inside the options object you pass to `mount()`, and the handle's `setAlignment()` moves a mounted trigger component.

## Platform notes

* **iOS.** The SDK installs on iOS 15, but trigger components draw only on iOS 17 or later. Below that they render nothing. `EncoreTriggerView` (UIKit) takes `publisherReward` and `onResult` as properties you set after creating it; `GiftsButtonView(placement:)` and `ClaimReminderView(placement:)` take them directly when you create them. Pin a UIKit view's leading and trailing edges, not its height.
* **Android.** Android 7.0 (API 24) or later. `EncoreTriggerView`'s constructor doesn't take `publisherReward`, `onResult` or `alignment`; set them as properties. On `GiftsButtonView` and `ClaimReminderView`, `alignment` is a property too. On `EncoreTriggerView` the ID property is `triggerId`, because `View.id` is already the view's integer ID. XML attributes carry an `encore` prefix: `app:encoreTriggerId`, `app:encorePlacement`, `app:encoreUseCase`, `app:encoreIcon`, `app:encoreAlignment`, and `app:encoreAutoOpen`. Use `wrap_content` for the height.
* **React Native.** React Native 0.72 or later. The trigger components render the native trigger view, so they need the native module linked: in Expo Go, or with React Native for web, they render nothing and log one warning. A `style` sets the width and margins; the height always comes from the trigger component. When you read `onResult`, check `result.status === 'presented'` before reading `result.claim`.
* **Flutter.** iOS 17 or later (the plugin installs on iOS 15), and Android API 26 or later. Android and iOS only: on the web and desktop the widgets render nothing. Give them a bounded width, as inside a `Column` or `ListView`.
* **Web.** `mount()` returns a handle; call `unmount()` when you remove the element. The React components clean up for you and render inside the `EncoreProvider` from [React](/publishers/web/frameworks/react). If you serve the SDK's ES module build yourself, serve the whole `dist/esm` folder: trigger components load from its `chunks` folder on first use, so a page without them never downloads them.

## Next steps

* [Gifts Button](/publishers/triggers/gifts-button): what it shows and paying your prize.
* [Claim Reminder](/publishers/triggers/claim-reminder): what it shows and when.
* [Experiments and looks](/publishers/triggers/experiments): how Encore picks and tests looks.
* [Troubleshooting](/publishers/triggers/troubleshooting): why a trigger component isn't showing.


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