---
name: lifepeaks-order-page
description: |
  Teaches an AI agent to read and customize a Lifepeaks order page via the Lifepeaks MCP server.
  Use when the user wants to configure, brand, or update a Lifepeaks order page — including
  changing colors, copy text, toggle flags, links, GTM tags, or i18n translations.
  Trigger keywords: lifepeaks, order page, orderpage, orderform, lp_live, lifepeaks MCP,
  customize order page, brand order page, order page config, order page fields.
---

# Lifepeaks Order Page Skill

This skill teaches an AI agent how to customize a Lifepeaks order page using the
Lifepeaks MCP server (`/mcp`). The MCP server speaks the standard MCP JSON-RPC protocol
and is backed by the same service layer as the REST API.

## Authentication

All MCP requests require a Bearer API key with the `lp_live_` prefix:

```
Authorization: Bearer lp_live_<your-key>
```

The key must have at minimum `orderpage:read` scope to read and `orderpage:write` scope
to draft and publish. Keys are issued via the admin UI or `POST /v2/api-keys`. The server
registers only the tools the key holds the scope for, so a read-only key never sees a
write tool.

## Available Tools

| Tool | Scope required | Description |
|---|---|---|
| `orderpage_get_current` | `orderpage:read` | Read the live configuration and published revision metadata |
| `orderpage_list_fields` | `orderpage:read` | List every writable field with its type and constraints |
| `orderpage_list_revisions` | `orderpage:read` | List draft, published, and archived revisions |
| `orderpage_get_revision` | `orderpage:read` | Read one revision, including its fields and ETag |
| `orderpage_preview_draft` | `orderpage:read` | Preview a draft without touching the live page |
| `orderpage_create_draft` | `orderpage:write` | Start a draft — the live page is unchanged |
| `orderpage_update_draft` | `orderpage:write` | Edit a draft using its exact ETag |
| `orderpage_publish_draft` | `orderpage:write` | Publish a reviewed draft to the live page |

There is also a resource (`orderpage://schema`) and a built-in prompt
(`customize_order_page`) that mirrors the workflow below.

## Standard Workflow

Changes go through a draft, so nothing reaches buyers until it is published. Always
follow this order:

1. **`orderpage_list_fields`** — discover which fields exist, their types, maximum lengths, and whether they hold a separate value per locale.
2. **`orderpage_get_current`** — read what is live today, so you know what you are changing.
3. **`orderpage_create_draft`** — start a draft. Keep the returned `id` and `etag`.
4. **`orderpage_update_draft`** — write the fields, using the newest `etag`.
5. **`orderpage_preview_draft`** — review the exact payload the page would render, and show it to the user.
6. **`orderpage_publish_draft`** — publish once the user approves.

### Write arguments

Every write tool takes an `idempotency_key`: a stable string of 16 to 255 characters,
generated once per logical action and reused unchanged on retry. Never generate a new one
inside a retry.

`orderpage_update_draft` and `orderpage_publish_draft` also take `confirm`, which must be
`true`. Send it only after the user has explicitly approved that specific change; an
unconfirmed call returns an error instead of acting.

### orderpage_update_draft input shape

```json
{
  "revision_id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64",
  "fields": {
    "field_name": "new_value",
    "another_field": 1
  },
  "etag": "\"opr_7c1e93a4b60d48f2a5e7c081b3d92f64:v1\"",
  "idempotency_key": "orderpage_draft_edit_018f4f37b949",
  "confirm": true
}
```

Only supply fields you intend to change. Unknown or sensitive fields cause a runtime
error, and nothing is written. Each successful edit returns a new ETag — use that one on
the next call.

## Field Categories

Fields returned by `orderpage_list_fields` belong to five groups:

### theme
Color tokens for the order-page UI.

| Field | Type | Notes |
|---|---|---|
| `orderform_company_box_bg` | `color` | Background color of the company box. Must be `#rrggbb` (7 chars). |

### copy (i18n-capable)
Text strings displayed on the order page. Fields marked `i18n: true` can be written
per-locale by passing a `lang` argument (see [i18n](#i18n) below).

| Field | Type | Max | i18n |
|---|---|---|---|
| `orderform_text_option` | string | — | yes |
| `orderform_text_value` | string | — | yes |
| `orderform_text_variant` | string | — | yes |
| `orderform_text_event` | string | — | yes |
| `orderform_text_specialoffer` | string | — | yes |
| `orderform_text_ticketcoupon` | string | — | yes |
| `orderform_signup_text` | string | 2000 | yes |
| `tagline` | string | — | yes |
| `payment_terms_all` | string | — | yes |
| `payment_terms_ticket` | string | — | yes |
| `payment_terms_benefitdeal` | string | — | yes |
| `footer_name` | string | 4000 | yes |

### links
URLs and link-related strings. Not i18n-capable.

| Field | Type | Max |
|---|---|---|
| `order_link` | string | 1000 |
| `order_link_text` | string | 100 |
| `order_link_subheading` | string | 255 |
| `order_logo_link_url` | string | 1000 |
| `orderform_policy_link` | string | 255 |
| `orderform_policy_link_benefit_deals` | string | 255 |
| `orderform_thankyou_redirect` | string | 1000 |

### flags
Boolean toggles (`0` or `1`). Not i18n-capable.

| Field | Default meaning |
|---|---|
| `orderform_greetings_with_image` | Include image in greeting card flow |
| `orderform_unsplash_enabled` | Allow Unsplash images in greetings |
| `specials_with_greetings` | Enable greetings for special offers |
| `benefitdeals_with_greetings` | Enable greetings for benefit deals |
| `manually_created_personalize` | Enable personalization for manually created items |
| `variants_visible_only_direct` | Hide variants from aggregated listing |
| `tickets_visible_only_direct` | Hide tickets from aggregated listing |
| `specials_visible_only_direct` | Hide specials from aggregated listing |
| `ticketcoupons_visible_only_direct` | Hide ticket coupons from aggregated listing |
| `orderform_gc_phone_required` | Require phone number on gift card checkout |
| `link_priority_order` | Show custom link above product list |
| `custom_mail_sender_enabled` | Use company custom mail sender |
| `variant_images_full` | Show variant images full-width |
| `orderform_logo_full_width` | Render logo full-width |
| `logo_in_menu` | Show logo inside navigation menu |
| `postmail_use_phone` | Use phone for postal mail contact |

### other

| Field | Type | Max | Notes |
|---|---|---|---|
| `orderform_languages` | `csv` | 20 | Comma-separated locale codes (e.g. `da-DK,en-GB`) |
| `preset_buttons` | `csv` | — | Comma-separated preset amount buttons |
| `gtm` | `gtm` | 20 | Google Tag Manager ID, format `GTM-XXXXXXX` |

## Type Validation Rules

| Type | Accepted values |
|---|---|
| `string` / `csv` | Any string within the `max` length limit |
| `bool` | Integer `0` or `1` (or string `"0"` / `"1"`) |
| `color` | 7-character hex `#rrggbb` (case-insensitive) |
| `gtm` | `GTM-` followed by uppercase alphanumeric characters, max 20 chars |
| `int` | Integer value |

## i18n

Fields with `i18n: true` hold a separate value per locale. A draft covers exactly one
locale, chosen when you create it:

```json
{
  "lang": "da-DK",
  "name": "Danish copy",
  "idempotency_key": "orderpage_draft_da_018f4f37b949"
}
```

Omitting `lang` targets the default locale (`en-GB`). To translate a page into several
locales, create and publish one draft per locale.

To read values in a specific locale over REST, use `GET /v2/order-page?lang=da-DK`.

## What Is NOT Writable

The following are intentionally excluded from the safe-field catalog and will be rejected:

- Raw HTML, CSS, or JavaScript injections (`orderform_css`, `orderform_code`, etc.)
- Payment fees and commission rates
- Any field not returned by `orderpage_list_fields`

Attempting to update a non-catalog field produces a runtime error.

## Worked Examples

### Example 1 — Set the Danish brand color and signup text

Goal: change the company box background to `#2d3a8c` and set the Danish signup text.

```
// Step 1: confirm the fields exist and check their constraints
orderpage_list_fields()
// → orderform_company_box_bg (color, max 7), orderform_signup_text (string, max 2000, i18n: true)

// Step 2: read what is live today
orderpage_get_current({ "lang": "da-DK" })
// → { "fields": { "orderform_company_box_bg": "#ffffff", "orderform_signup_text": "Sign up", ... } }

// Step 3: start a Danish draft
orderpage_create_draft({
  "lang": "da-DK",
  "name": "Danish brand refresh",
  "idempotency_key": "orderpage_draft_da_018f4f37b949"
})
// → { "id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64", "etag": "\"opr_7c1e…:v1\"", ... }

// Step 4: write both fields in one edit, using that ETag
orderpage_update_draft({
  "revision_id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64",
  "fields": {
    "orderform_company_box_bg": "#2d3a8c",
    "orderform_signup_text": "Tilmeld dig eksklusive fordele"
  },
  "etag": "\"opr_7c1e93a4b60d48f2a5e7c081b3d92f64:v1\"",
  "idempotency_key": "orderpage_draft_da_edit_018f4f37b949",
  "confirm": true
})
// → returns the draft with a NEW etag, "…:v2"

// Step 5: show the user the exact payload before anything goes live
orderpage_preview_draft({ "revision_id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64" })

// Step 6: publish once the user approves, with the newest etag
orderpage_publish_draft({
  "revision_id": "opr_7c1e93a4b60d48f2a5e7c081b3d92f64",
  "etag": "\"opr_7c1e93a4b60d48f2a5e7c081b3d92f64:v2\"",
  "idempotency_key": "orderpage_publish_da_018f4f37b949",
  "confirm": true
})
```

### Example 2 — Enable GTM and hide variants from the listing

Goal: add GTM tracking and hide variants from the aggregated product listing. Neither
field is per-locale, so one draft in the default locale is enough.

```
// Step 1: check what is live
orderpage_get_current()
// → { "fields": { "gtm": null, "variants_visible_only_direct": 0, ... } }

// Step 2: start a draft
orderpage_create_draft({
  "name": "Analytics and listing",
  "idempotency_key": "orderpage_draft_gtm_018f4f37b949"
})
// → { "id": "opr_2b8f04d7c19e4a6035fd82c7e1b940a3", "etag": "\"opr_2b8f…:v1\"", ... }

// Step 3: write both fields together
orderpage_update_draft({
  "revision_id": "opr_2b8f04d7c19e4a6035fd82c7e1b940a3",
  "fields": { "gtm": "GTM-ABC1234", "variants_visible_only_direct": 1 },
  "etag": "\"opr_2b8f04d7c19e4a6035fd82c7e1b940a3:v1\"",
  "idempotency_key": "orderpage_draft_gtm_edit_018f4f37b949",
  "confirm": true
})

// Step 4: preview, then publish with the newest etag
orderpage_preview_draft({ "revision_id": "opr_2b8f04d7c19e4a6035fd82c7e1b940a3" })
orderpage_publish_draft({
  "revision_id": "opr_2b8f04d7c19e4a6035fd82c7e1b940a3",
  "etag": "\"opr_2b8f04d7c19e4a6035fd82c7e1b940a3:v2\"",
  "idempotency_key": "orderpage_publish_gtm_018f4f37b949",
  "confirm": true
})
```

## Error Handling

A rejected write returns a runtime error carrying a JSON payload. Read it to see which
field is at fault, correct it, and retry. The common causes are:

- A field name that is not in the catalog from `orderpage_list_fields`.
- A value of the wrong type, such as a string where `bool` is expected.
- A value longer than the field's `max`.
- A stale `etag`, meaning the draft changed since you read it. Call `orderpage_get_revision`, reconcile, and retry with the new ETag.
- A missing or `false` `confirm` on a write that requires approval.
