Skip to main content

HTML page structure

A minimal page structure with a header, an optional sidebar, and a widget in the main area.
  • The script is loaded once in the <head>.
  • a-login-button and a-cart-modal-button belong in the header, so they stay visible on all pages.
  • Replace the panel with a page widget using fullscreen="true" and nav-height if the booking should fill the entire viewport height (see Full-page widgets further below).

Full-page widgets

Page widgets are suitable when the widget is the main content of the page. Page widgets:
  • a-organization-page
  • a-organization-map
  • a-organization-calendar
  • a-resource-page
  • a-resource-map
  • a-resource-calendar
  • a-service-page
  • a-subscription-page
  • a-package-page
  • a-my-bookings
Use fullscreen="true" so the widget fills the available viewport height. If your website has a fixed header, also pass nav-height so the widget is not rendered underneath it.
Notes:
  • fullscreen="true" corresponds to height: 100vh.
  • nav-height changes this to calc(100vh - nav-height).
  • If you set height, automatic resizing is disabled and the iframe has a fixed height.
  • For *-page, map, calendar, and a-my-bookings widgets, full-page layouts are usually the cleanest integration.

Organization map and organization calendar

These are page widgets, not modal buttons. Treat them like a full page section.
Use the organization map when the map is the primary interface. Use the organization calendar when availability navigation is the focus. If you want the full explore flow instead, use a-organization-page.

Panels

Booking panels are deliberately kept compact and lock the navigation. Panel widgets:
  • a-resource-booking-panel
  • a-service-booking-panel
Important behavior:
  • Panels always use dynamic height.
  • External height and fullscreen values are ignored.
  • Panels are meant to embed the booking flow into your own page layout.

Popups from the widget

The widget opens a separate browser window for some steps. This is not only about payment — login and logout always need this window, even if you do not offer external payment methods. The widget opens a popup for:
  • Login and logout via the login button, or when a booking requires sign-in
  • External payments such as PayPal, iDEAL, giropay, Sofort, Bancontact, EPS, Przelewy24, or TWINT
  • Card verification (3-D Secure) when the bank asks for an extra confirmation
Your website must allow these windows. Otherwise the window stays blank, or the browser shows This content is blocked. Contact the site owner to fix the issue. Login and payment then cannot finish.
A common blocker is the HTTP header Cross-Origin-Opener-Policy set to same-origin. The browser then isolates every window the widget opens from the iframe.

What you need to set on your website

  1. Set Cross-Origin-Opener-Policy to same-origin-allow-popups — or remove the header.
  2. Allow pop-ups for your booking page (browser and, if applicable, company policy).
  3. Do not change X-Frame-Options or frame-ancestors just for this. Those control whether your page may be embedded, not whether the widget may open a window.
The anny booking page on anny.co is not affected. Until the header change is live, customers can book there instead of in the website widget.

External payments in the widget

When customers choose a payment method in embedded checkout that leaves anny (PayPal, iDEAL, giropay, Sofort, Bancontact, EPS, Przelewy24, TWINT), the widget opens the payment page in a centered popup. Card and SEPA stay in the widget (Stripe overlay). Prerequisites for that window: Popups from the widget. The checkout hint reads: Your booking must be paid online. For this purpose, a new window will open where you can make the payment. After that the window will close automatically. If the browser blocks the popup, the widget shows Your browser blocked the payment window and the Open payment page button. The widget does not load the payment page inside itself. The host page is not navigated.

Login button and cart button

These two components are configured under Organization → Settings → Booking page → Global components. They are intended as shared controls that are usually located in the site header or in a fixed navigation bar.

Login button

Use a-login-button when you need a shared login/logout element that stays in sync with the widget session.
Behavior:
  • Loads its own login iframe.
  • Opens login and logout in a popup. Your website must allow that window, see Popups from the widget.
  • Automatically switches to the logged-in avatar state.
  • Forwards auth changes so neighboring widgets update their authentication state.
Good placements:
  • Main site header
  • Mobile navigation drawer
  • Top bar on booking landing pages

Cart button

Use a-cart-modal-button when users should add items from booking widgets and check out later.
Behavior:
  • Shows a live badge with the item count.
  • Stays in sync with neighboring widgets on the same page.
  • Opens the checkout in a modal overlay.
Common combinations:
  • a-resource-booking-panel together with a-cart-modal-button
  • Several booking widgets on one page with a shared cart button

Events and tracking

Most embed widgets forward booking lifecycle events as DOM custom events. This applies to everything except the login button. Supported event names:
  • view-page
  • add-to-cart
  • start-checkout
  • complete-checkout
Common fields in the event payload:
  • event_name
  • value
  • gross_value
  • tax
  • currency
  • transaction_id
  • items
Example:
GA4 example:
Notes:
  • a-login-button and a-cart-modal-button are helper widgets and do not send booking events.
  • Page widgets, maps, calendars, booking panels, and checkout-focused pages send booking events.
  • Subscription and package widgets send checkout-focused events. In practice, view-page, start-checkout, and complete-checkout are the most relevant.

UTM parameters and click IDs

You don’t need to do anything else for attribution. When a widget loads, it reads the query string of the parent page URL and automatically forwards these parameters into the embedded iframe: So if a user arrives on your page via ?utm_campaign=spring&gclid=abc123, the widget carries these values through the entire booking flow. Conversion tracking works without any additional configuration. No HTML attribute is required. The forwarding happens automatically on every widget load.

Start and end date

Most widgets accept start (and sometimes end) to pre-navigate the calendar or map to a specific date range. ISO 8601 date string for an exact date:
Relative keyword value that is resolved at render time:
Relative values are supported everywhere, except for a-resource-calendar and a-organization-calendar, which require ISO 8601. end always expects an ISO 8601 date string.

Customization options by widget type

This section documents the public HTML attributes. Admin-generated snippets usually already cover the most important ones.

Common attributes for embed widgets

Applies to page widgets and panel widgets. Not applicable to button widgets. All embed widgets additionally accept the design attributes from WIDGET_DESIGNING.md.

Organization widgets

a-organization-page

Note:
  • The “Calendar board” option in the admin corresponds to calendar-view="list".

a-organization-calendar

a-organization-map

Resource widgets

a-resource-page

a-resource-calendar

a-resource-map

a-resource-booking-panel

Service widgets

a-service-page

a-service-booking-panel

Subscription and package widgets

a-subscription-page

a-subscription-button

a-package-page

a-package-button

Button widgets

Applies to:
  • a-organization-button
  • a-resource-button
  • a-service-button
  • a-subscription-button
  • a-package-button
  • a-modal-button
  • a-cart-modal-button

Common modal attributes

Trigger attributes for entity buttons

Applies to:
  • a-organization-button
  • a-resource-button
  • a-service-button
  • a-subscription-button
  • a-package-button
a-modal-button is different:
  • no label prop
  • no built-in trigger styling props
  • use your own element in the slot as the trigger

Custom trigger (slot)

All button widgets accept a default slot that replaces the built-in trigger. Use this when you want to style the trigger yourself or use a different element as the button.
When a slot is used, label, button-background, button-text, and button-width are ignored. Click and keyboard handling are still managed by the widget wrapper.

a-resource-button

a-service-button

a-organization-button

a-modal-button

Use this button when you need a custom modal trigger without an entity-specific button component.

Helper widgets

a-cart-modal-button

a-login-button

a-my-bookings

Note:
  • a-my-bookings always requires authentication. should-login is not available, since login is mandatory.

External payment in embedded checkout

When customers pay in the widget with an external payment method (for example PayPal, iDEAL, Giropay, Sofort, Bancontact, EPS, Przelewy24, or TWINT), anny opens the payment page in its own centered window. Your website and the widget stay open, and checkout keeps the data already entered. Card and SEPA payments stay in the widget. If the payment window is blocked, the Open payment page button appears — payment does not continue inside the widget iframe. If someone closes the window before payment finishes, they see a message that the payment could not be processed. For login and payment to open a window reliably, see Popups from the widget.

Recommendations

  • Use the admin-generated snippet first and only refine it manually when needed.
  • Use page widgets for dedicated booking pages.
  • Use panels for editorial pages around the booking flow.
  • Use button widgets when booking should only become visible after a click.
  • Place a-login-button and a-cart-modal-button in stable, clearly visible positions in the UI.
  • Make sure your website allows popups from the widget — login needs them even without payment. See Popups from the widget.
  • Prefer drawer for desktop-side checkout flows and fullscreen for mobile experiences.