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

# placement()

> Fluent builder for presenting offers at a named placement: placement(id, options) records the claim under the id, show({ receipt? }) presents with per-surface layout/appearance/display options and a per-placement redemptionMode, and redeem() completes that placement's deferred claim.

Returns a fluent builder for presenting offers at a **named placement**. The id is recorded
on the claimed transaction so `placement(id).redeem()` can later resolve exactly that claim;
the options carry per-surface UI configuration.

## Signature

```typescript theme={null}
function placement(
  idOrOptions?: string | PlacementOptions,
  options?: PlacementOptions
): PlacementBuilder
```

All argument combinations work:

```javascript theme={null}
Encore.placement()                                            // anonymous, defaults
Encore.placement('cancel_flow')                               // named placement
Encore.placement({ appearance: { accentColor: '#5671FF' } })  // options only
Encore.placement('post-purchase', { layout: 'thankYou' })     // named + options
```

## PlacementOptions

### Structure

`PlacementOptions` is a union of two layout variants sharing a common base:

```typescript theme={null}
// Common to every layout
interface BasePlacementOptions {
  appearance?: { backgroundColor?: string; textColor?: string; accentColor?: string };
  header?: { icon?: 'success' | 'none'; title?: string; subtitle?: string };
  display?: { appDisplayName?: string; trialPeriod?: string; logoUrl?: string };
  redemptionMode?: 'deferred' | 'immediate';  // per-placement; default from configure()
}

// The default offer sheet
interface ListPlacementOptions extends BasePlacementOptions {
  layout?: 'list';
}

// The post-purchase success composition
interface ThankYouPlacementOptions extends BasePlacementOptions {
  layout: 'thankYou';
  offerContext?: { title?: string; subtitle?: string };  // priming copy above the offers
  footer?: { text?: string };                            // trust line below the carousel
}

type PlacementOptions = ListPlacementOptions | ThankYouPlacementOptions;
```

### Field Reference

| Field                              | Type                                          | Applies to                                     | Description                                                                                                                                                                                                                                                                                                                              |
| ---------------------------------- | --------------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `appearance`                       | `AppearanceConfig`                            | both layouts                                   | `accentColor`, `backgroundColor`, `textColor`: CSS color strings.                                                                                                                                                                                                                                                                        |
| `layout`                           | `'list' \| 'thankYou'`                        | -                                              | Layout template; default `'list'` (the offer sheet). Unknown values fall back to `'list'` with a warning.                                                                                                                                                                                                                                |
| `redemptionMode`                   | `'deferred' \| 'immediate'`                   | both layouts                                   | Per-placement override of the `configure()` default: the claim↔redeem coupling for this surface. See [Redemption Modes](/publishers/web/concepts/redemption-modes).                                                                                                                                                                      |
| `display`                          | `{ appDisplayName?, trialPeriod?, logoUrl? }` | both layouts (consumed by `'list'` · deferred) | Local override of the portal-managed host display values the deferred screens render; required to *resolve* (locally or remotely) in `'list'` · deferred. See [Display Resolution](/publishers/web/concepts/display-resolution).                                                                                                         |
| `header.title` / `header.subtitle` | `string`                                      | both layouts                                   | Top heading block; an explicit value always wins. Defaults: in `'list'` · deferred, the composed "Get {app} free for {trial}" / "Claim a partner offer to start"; in `'list'` · immediate, the remote/generic copy; in `'thankYou'`, `title` defaults to "Payment Successful", and a `receipt` passed to `show()` supersedes `subtitle`. |
| `header.icon`                      | `'success' \| 'none'`                         | `'thankYou'` only                              | Status check above the title; `'success'` (default) renders the green check, `'none'` hides it. Ignored by `'list'`.                                                                                                                                                                                                                     |
| `offerContext`                     | `{ title?, subtitle? }`                       | `'thankYou'` only                              | Priming copy above the offers. The `subtitle` is a fallback; the active offer's campaign `perk` line supersedes it.                                                                                                                                                                                                                      |
| `footer.text`                      | `string`                                      | `'thankYou'` only                              | Trust line below the carousel; omitted → not rendered.                                                                                                                                                                                                                                                                                   |

In the `'thankYou'` layout the blocks render top to bottom: check icon → `header.title` →
status subtitle (the `receipt` passed to [`show()`](/publishers/web/sdk-reference/show),
else `header.subtitle`) → `offerContext` copy → the carousel → `footer.text`.

Usage end to end:
[Reduce Paywall Churn](/publishers/web/guides/intercept-paywall-abandonment) (`'list'` · deferred) ·
[Post-Purchase Placements](/publishers/web/guides/post-purchase-placements) (`'thankYou'`).

## PlacementBuilder

```typescript theme={null}
interface PlacementBuilder {
  show(options?: { receipt?: { amount: string; purpose?: string } }): Promise<ShowResult>;
  redeem(): Promise<RedeemResult>;
  onNotGranted(callback: (reason: NotGrantedReason) => void): PlacementBuilder;
  onLoadingStateChange(callback: (isLoading: boolean) => void): PlacementBuilder;
}
```

### show(options?)

Presents the offer carousel with this placement's options and resolves the bare
[`ShowResult`](/publishers/web/sdk-reference/show)
(`'claimed' | 'dismissed' | 'unavailable'`). On a `thankYou`-layout placement, pass the
per-transaction `receipt`, rendered as the "You paid … for …" subtitle line
(render-only, never sent to Encore's servers).

### redeem()

Redeems the claim recorded at **this** placement, phase 2 of the
[deferred flow](/publishers/web/concepts/redemption-modes#deferred-mode-the-two-phase-flow).
It never resolves another placement's transaction (resolves `{ status: 'none' }` if this
placement has no pending claim). Contract: [`redeem()`](/publishers/web/sdk-reference/redeem).

### onNotGranted(callback)

Fires when the sheet closes without a claim, carrying the dismissal reason (the same
`NotGrantedReason` a `dismissed` result carries).

### onLoadingStateChange(callback)

Fires `true` when the presentation starts loading and `false` when it settles; useful for
spinners and disabling the triggering button. Callbacks are scoped to this builder instance;
they don't persist across calls.

## Examples

### Two-phase flow at a named placement

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

// Phase 1: claim (deferred mode, no redirect yet)
const result = await Encore.placement('cancel_flow')
  .onLoadingStateChange((isLoading) => setSpinner(isLoading))
  .show();
if (result.status !== 'claimed') return; // 'dismissed' | 'unavailable'

// Phase 2: later, from a click handler
const outcome = await Encore.placement('cancel_flow').redeem();
// outcome.status === 'redeemed' on success
```

### Post-purchase placement (thankYou layout)

```javascript theme={null}
const placement = Encore.placement('post-purchase', {
  layout: 'thankYou',
  redemptionMode: 'immediate', // one-tap claim on this surface only
  appearance: { accentColor: '#0A6' },
  footer: { text: 'Secured by Acme' },
});

const result = await placement.show({ receipt: { amount: '$9.99', purpose: 'Pro Plan' } });
// result.status === 'claimed' → the advertiser tab is already open (immediate mode)
```

## Related

* [`show()`](/publishers/web/sdk-reference/show): the `ShowResult` contract
* [`redeem()`](/publishers/web/sdk-reference/redeem): phase 2; placement-scoped resolution
* [Redemption Modes](/publishers/web/concepts/redemption-modes): the `redemptionMode` axis
* [Display Resolution](/publishers/web/concepts/display-resolution): how `display` and `header` values resolve
