# In-app messages

> Show Grovs in-app messages over a Unity game, hold them back during play, and react to taps and answers.

Source: https://docs.grovs.io/docs/sdk/unity/in-app-messages

In-app messages are dashboard campaigns: a banner, modal, full-screen cover, system alert, question or your own HTML. The native SDK downloads live campaigns, picks one on the device for each app open, screen view or event, and draws it over the game. To create campaigns, see [In-app messages](https://docs.grovs.io/docs/engagement/in-app-messages).

No code is required. Once the package is [set up](https://docs.grovs.io/docs/sdk/unity/quick-start), campaigns show. Use the calls below to keep messages out of gameplay or react to what the player did.

Screen-view triggers and excluded screens match the names you send with `TrackScreenView`, or scene names with [**Track scenes**](https://docs.grovs.io/docs/sdk/unity/analytics#tracking-scenes) on.

## React to messages

`Grovs.InAppMessageEvent` fires on the Unity main thread:

```csharp
using GrovsSDK;
using UnityEngine;

void OnEnable() => Grovs.InAppMessageEvent += OnInAppEvent;
void OnDisable() => Grovs.InAppMessageEvent -= OnInAppEvent;

void OnInAppEvent(InAppMessageEvent e)
{
    switch (e.Type)
    {
        case InAppEventType.Clicked:
            // Payload is set for a key-value action
            if (e.Payload != null && e.Payload.TryGetValue("reward", out var reward)) GiveReward(reward);
            break;
        case InAppEventType.Dismissed:
            Debug.Log("Dismissed: " + e.DismissReason);
            break;
        case InAppEventType.Answered:
            Debug.Log("Answer: " + e.AnswerValue + " " + e.Comment);
            break;
        case InAppEventType.Failed:
            Debug.LogWarning(e.FailureMessage);
            break;
    }
}
```

| Field            | Set for     | Description                                                       |
| ---------------- | ----------- | ----------------------------------------------------------------- |
| `Type`           | All         | `Shown`, `Clicked`, `Dismissed`, `Answered` or `Failed`           |
| `CampaignId`     | All         | The campaign. Can be `null` for `Failed` on iOS.                  |
| `ButtonId`       | `Clicked`   | The tapped button. `null` when the message body was tapped.       |
| `Payload`        | `Clicked`   | The pairs of a key-value action, else `null`                      |
| `DismissReason`  | `Dismissed` | `close_button`, `backdrop`, `swipe`, `app` or `orientation`       |
| `AnswerValue`    | `Answered`  | A `long` (1 to 5) for stars, or a `string` option ID for a choice |
| `Comment`        | `Answered`  | The player's comment, or `null`                                   |
| `FailureMessage` | `Failed`    | Why the message couldn't be shown                                 |

A `Failed` event is also reported to `ErrorOccurred` with code `InAppDisplayFailed`.

## Hold a message back

Set a veto. Return `false` to skip a message, `true` to show it:

```csharp
// Read a plain field here, updated from game code.
static volatile bool inMatch;

Grovs.ShouldShowInAppMessage = campaignId => !inMatch;
```

> **Warning:** `ShouldShowInAppMessage` runs synchronously on a native thread. On iOS that's the main thread. On Android it's the Android UI thread, which **isn't** Unity's thread. Keep it fast and don't call Unity APIs from it. Read a field you update from game code instead.

`null` (the default) shows every message. If the delegate throws, the exception is logged and the message shows.

## Pause and exclude

```csharp
// During a boss fight. The newest highest priority message waits.
Grovs.PauseInAppMessages();

// Show messages again, starting with the one that waited, if it still qualifies.
Grovs.ResumeInAppMessages();

// Drop the waiting message. Pass true to also close the one on screen.
Grovs.DiscardInAppMessages(dismissCurrent: true);

// No message shows on these screens.
Grovs.SetInAppExcludedScreens(new List<string> { "Gameplay" });
```

`SetInAppExcludedScreens(null)` clears the list.

## Over the game

|                         | iOS                    | Android                                                                                       |
| ----------------------- | ---------------------- | --------------------------------------------------------------------------------------------- |
| Where the message draws | A window above Unity's | A dialog over the Unity activity. Unity may get `OnApplicationFocus(false)` while it's shown. |
| Veto thread             | Main thread (Unity's)  | Android UI thread (not Unity's)                                                               |

## Debugging

```csharp
Grovs.SetLogLevel(GrovsLogLevel.Info);
Grovs.SetInAppDebugLogging(true);
```

The native SDK then logs each campaign considered for an event and why it was skipped.

## Native behavior

Triggers, sync, frequency caps, button actions, questions, custom HTML and test messages work as in the native SDK. See [iOS in-app messages](https://docs.grovs.io/docs/sdk/ios/in-app-messages) for the details and the reserved event names.

## See also

- [In-app messages](https://docs.grovs.io/docs/engagement/in-app-messages): create campaigns
- [Events & screen tracking](https://docs.grovs.io/docs/sdk/unity/analytics): the events and screens that trigger messages
- [API reference](https://docs.grovs.io/docs/sdk/unity/api-reference#in-app-messages)
