> ## 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.

# show()

> Present the offer carousel — phase 1 of the two-phase flow. Resolves a bare ShowResult: 'claimed' (in immediate mode the advertiser tab was also opened first), 'dismissed', or 'unavailable'. The SDK renders nothing after a claim, and show() never rejects.

Presents the offer carousel and resolves when the user claims an offer, dismisses the carousel,
or no offers are eligible. `show()` is **phase 1** of the two-phase flow — pair it with
[`redeem()`](/publishers/web/sdk-reference/redeem) in deferred mode.

## When to use this

Call `show()` at the moment you want to present an offer — a cancel flow, a paywall, an
onboarding step. What it does on claim depends on
[`redemptionMode`](/publishers/web/guides/redemption-modes):

* **deferred** (default): records a transaction and resolves `claimed` with **no redirect** —
  call [`redeem()`](/publishers/web/sdk-reference/redeem) later.
* **immediate**: also opens the advertiser in a new tab (inside the claim gesture), then
  resolves the same `claimed`.

In **both** modes the SDK renders nothing after a claim — there is no built-in success or
confirmation screen. The host owns the post-claim moment: render your own confirmation (or
none), keyed off the result.

Most integrations present via the fluent
[`placement(id).show()`](/publishers/web/sdk-reference/placement) builder, which resolves
the same `ShowResult`; `Encore.show()` is the inline one-call variant.

## Signature

```typescript theme={null}
function show(
  options?: {
    receipt?: { amount: string; purpose?: string };  // 'thankYou' layout only — rendered as the status subtitle
  },
  placementOptions?: PlacementOptions,  // per-presentation UI: layout, appearance, header, offerContext, footer
  placementId?: string                  // recorded on the transaction for placement-scoped redeem()
): Promise<ShowResult>
```

`placementOptions` and `placementId` mirror the fluent
[`placement(id, options).show()`](/publishers/web/sdk-reference/placement) form — the
placement id is recorded the same way.

### Parameters

| Parameter          | Type                                                          | Required | Description                                                                                                                                                                                                                     |
| ------------------ | ------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `options.receipt`  | `{ amount: string; purpose?: string }`                        | No       | Per-transaction payment context, rendered as the status subtitle under the [`thankYou` layout](/publishers/web/guides/thank-you-layout). Render-only — never sent to Encore's servers. Pass `amount` pre-formatted (`'$9.99'`). |
| `placementOptions` | [`PlacementOptions`](/publishers/web/sdk-reference/placement) | No       | Per-presentation UI overrides. Full field contract in [`placement()`](/publishers/web/sdk-reference/placement); post-purchase usage in the [Thank-You Layout guide](/publishers/web/guides/thank-you-layout).                   |
| `placementId`      | `string`                                                      | No       | Placement key recorded on the transaction, so a later [`placement(id).redeem()`](/publishers/web/sdk-reference/redeem) resolves this exact claim.                                                                               |

## ShowResult

```typescript theme={null}
type ShowResult =
  | { status: 'claimed' }                                // user claimed an offer (both modes)
  | { status: 'dismissed';  reason?: NotGrantedReason }  // user closed/declined — or an internal error
  | { status: 'unavailable' };                           // no eligible offers (or a control-cohort ghost trigger)
```

The result is **bare** — no transaction handle, no reward copy. `claimed` is identical in
both [redemption modes](/publishers/web/guides/redemption-modes); the only difference is a
side effect: in immediate mode the advertiser tab was also opened before `show()` resolved.

| `status`      | When                                                                                                                | Next step                                                                                                                                                                                                        |
| ------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `claimed`     | User claimed an offer                                                                                               | Deferred: run your conversion, then [`redeem()`](/publishers/web/sdk-reference/redeem) — no handle needed. Immediate: nothing — the advertiser tab is already open; render your own confirmation if you want one |
| `dismissed`   | User closed the modal, clicked outside, or declined the last offer — or the flow failed (`reason.type === 'error'`) | Respect the decline; `reason` says which                                                                                                                                                                         |
| `unavailable` | No eligible offers — **or** the user is in a measurement control cohort                                             | Show your fallback; do not assume which                                                                                                                                                                          |

`reason` (a `NotGrantedReason`) is one of `'userClosedModal'`, `'userClickedOutside'`,
`'userDeclinedLastOffer'`, `'noOffersAvailable'`, or `{ type: 'error', error }`.

<Note>
  **`show()` never rejects.** There is no crash path and no `try/catch` needed: any failure
  (SDK not configured, network error, unexpected exception) resolves as
  `{ status: 'dismissed', reason: { type: 'error', error } }`.
</Note>

<Warning>
  **The result makes no conversion claim.** `claimed` means the user accepted an offer — the
  advertiser conversion happens later, asynchronously, via server-side postbacks. Verify
  conversions and entitlements **server-side, by user**, with Encore's
  Encore’s server-side verification —
  never from the client, and never from this result.
</Warning>

Deferred hosts never need to track pending state themselves (even across a reload): call
[`redeem()`](/publishers/web/sdk-reference/redeem) when your flow is ready — the SDK resolves
the pending transaction internally, and if nothing is pending it resolves `{ status: 'none' }`.

## Examples

### Deferred (default)

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

const result = await Encore.show();

switch (result.status) {
  case 'claimed':
    // No redirect yet. Run your own conversion, then call Encore.redeem() —
    // the SDK resolves the pending transaction internally; no handle needed.
    break;
  case 'dismissed':
    // result.reason === 'userClosedModal' | 'userDeclinedLastOffer' | { type: 'error', ... }
    break;
  case 'unavailable':
    showFallback();
    break;
}
```

### Immediate

```javascript theme={null}
// Configured with redemptionMode: 'immediate'
const result = await Encore.show();
if (result.status === 'claimed') {
  // Advertiser tab already opened inside the claim gesture. The SDK renders
  // nothing after the claim — show your own confirmation here if you want one.
}
```

## Gotchas

* **`unavailable` is overloaded.** It means "no eligible offers" *and* "measurement
  control cohort (ghost trigger)" — the SDK keeps them indistinguishable on purpose so
  incrementality experiments aren't contaminated. Don't branch app behavior on a suspected
  control assignment; just show your normal fallback.
* **Claim ≠ redirect in deferred mode.** `claimed` only records a transaction. The redirect is
  in [`redeem()`](/publishers/web/sdk-reference/redeem).
* **Nothing renders after a claim.** The SDK has no built-in success screen — if your flow
  needs a confirmation moment, render it yourself when the result is `claimed`.
* **Claim ≠ conversion.** Never grant access off a `claimed` result — verify entitlements
  server-side, by user (see the warning above).

## Related

* [`redeem()`](/publishers/web/sdk-reference/redeem) — phase 2 of the flow.
* [Redemption Modes](/publishers/web/guides/redemption-modes) — deferred vs immediate, full walkthrough.
* [placement](/publishers/web/sdk-reference/placement) — present at a named placement.
