Skip to main content

Widget Embeds - Advanced

Use this guide when you need precise control over layout, events, modal behavior, or direct HTML attributes.

Written by Lucian Holtwiesche

HTML Page Layout Example

Minimal page structure with a header, optional sidebar, and a widget in the main area.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Booking Page</title>
<script src="https://cdn.anny.co/widget/annyComponents.umd.latest.min.js"></script>
</head>
<body>

<header>
<a href="/">Your Logo</a>
<nav><!-- navigation --></nav>
<a-login-button base-url="https://anny.co"></a-login-button>
<a-cart-modal-button base-url="https://anny.co" modal-layout="drawer"></a-cart-modal-button>
</header>

<main>
<aside><!-- optional sidebar --></aside>

<div>
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
></a-resource-booking-panel>

<!-- additional page content -->
</div>
</main>

</body>
</html>
  • Load the script once in <head>.

  • Place a-login-button and a-cart-modal-button in the header so they stay visible on all pages.

  • Swap the panel for a page widget with fullscreen="true" and nav-height if booking should fill the viewport (see Full-Page Widgets below).


Full-Page Widgets

Use page widgets when the widget should behave like the main content area 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


Recommended integration for full-page layouts

Use fullscreen="true" when the widget should fill the available viewport height. If your website has a sticky header, also pass nav-height so the widget does not render underneath it.

<a-resource-calendar
base-url="https://anny.co"
resource="my-resource"
fullscreen="true"
nav-height="72px"
></a-resource-calendar>

Notes:

  • fullscreen="true" maps to height: 100vh.

  • nav-height changes that to calc(100vh - nav-height).

  • If you set height, auto-resize is disabled and the iframe becomes fixed-height.

  • For *-page, map, calendar, and a-my-bookings, full-height 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.

<a-organization-map
base-url="https://anny.co"
organization="my-org"
fullscreen="true"
></a-organization-map>

<a-organization-calendar
base-url="https://anny.co"
organization="my-org"
calendar-view="week"
fullscreen="true"
></a-organization-calendar>

Use organization map when the map is the primary UI. Use organization calendar when availability navigation is the primary UI. If you want the broader explore flow instead, use a-organization-page.


Panels

Booking panels are intentionally compact and keep navigation locked.

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 for embedding booking inside your own page layout.

<a-service-booking-panel
base-url="https://anny.co"
service="intro-call"
></a-service-booking-panel>

Login Button And Cart Button

These two components are configured in Organization -> Settings -> Booking page -> Global components. They are meant to be shared controls, usually in a site header or sticky nav.

Login button

Use a-login-button when you want a shared login/logout control that stays in sync with the widget session.

<a-login-button
base-url="https://anny.co"
locale="en"
idp-uuid="your-idp-uuid"
></a-login-button>

Behavior:

  • Loads a dedicated login iframe.

  • Switches to the logged-in avatar state automatically.

  • Broadcasts auth changes so sibling widgets can refresh auth state.

Good placement:

  • Main site header

  • Mobile navigation drawer

  • Booking landing page top bar

Cart button

Use a-cart-modal-button when users can add items from booking widgets and later check out.

<a-cart-modal-button
base-url="https://anny.co"
modal-layout="drawer"
label="Cart"
></a-cart-modal-button>

Behavior:

  • Shows a live item-count badge.

  • Stays in sync with sibling widgets on the same page.

  • Opens checkout in a modal overlay.

Best pairing:

  • a-resource-booking-panel plus a-cart-modal-button

  • Multiple booking widgets on one page with one shared cart trigger


Custom Events And Tracking

Most embed widgets forward booking lifecycle events as DOM custom events.

Supported event names:

  • view-page

  • add-to-cart

  • start-checkout

  • complete-checkout

Common event payload fields:

  • event_name

  • value

  • gross_value

  • tax

  • currency

  • transaction_id

  • items

Example:

<a-resource-page
id="booking-widget"
base-url="https://anny.co"
resource="my-resource"
></a-resource-page>

<script>
const widget = document.getElementById('booking-widget')

widget.addEventListener('complete-checkout', (event) => {
const data = event.detail
console.log('Checkout complete', data.transaction_id, data.gross_value, data.currency)
})
</script>

GA4 example:

<script>
const widget = document.getElementById('booking-widget')

widget.addEventListener('complete-checkout', (event) => {
const data = event.detail

gtag('event', 'purchase', {
currency: data.currency,
value: data.gross_value ?? data.value,
transaction_id: data.transaction_id,
items: (data.items || []).map((item) => ({
item_id: item.id,
item_name: item.name,
quantity: item.quantity,
price: item.price,
})),
})
})
</script>

Notes:

  • a-login-button and a-cart-modal-button are utility widgets, not booking event emitters.

  • Page widgets, maps, calendars, booking panels, and checkout-oriented pages emit booking events.

  • Subscription and package widgets emit checkout-focused events. In practice, view-page, start-checkout, and complete-checkout are the key ones there.


UTM Parameters And Click IDs

You do not need to do anything extra 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:

Parameter

Platform

utm_source, utm_medium, utm_campaign, utm_content, utm_term

All (Google Analytics, etc.)

gclid

Google Ads

fbclid

Meta / Facebook Ads

ttclid

TikTok Ads

li_fat_id

LinkedIn Ads

This means that if a user arrives on your page via ?utm_campaign=spring&gclid=abc123, the widget will carry those values through to the booking and conversion tracking will work without any extra configuration.

No HTML attribute is needed — forwarding happens automatically on every widget load.


Start And End Dates

Most widgets accept start (and sometimes end) to pre-navigate the calendar or map to a specific date range.

ISO 8601 date string — exact date:

<a-resource-page
base-url="https://anny.co"
resource="my-resource"
start="2025-06-15"
></a-resource-page>

Relative keyword — resolved at render time:

Value

Meaning

today

Current day

tomorrow

Next day

this_week

Start of the current week

next_week

Start of next week

this_month

Start of the current month

next_month

Start of next month

<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
start="tomorrow"
></a-resource-booking-panel>

Relative values are supported everywhere except 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 cover the most important ones.

Shared attributes for embed widgets

Applies to page widgets and panel widgets. Not applicable to button widgets.

Attribute

Purpose

base-url

Required. anny base URL, for example https://anny.co

locale

Force widget language. If omitted, browser language is used

height

Fixed iframe height, for example 700px or 80vh. Disables auto-resize. Not supported on button widgets.

fullscreen

Fill viewport height (100vh). Not supported on button widgets.

nav-height

Offset from viewport top when using fullscreen, for example 64px

should-login

Require login before booking

idp-uuid

SSO identity provider UUID

logo-url

Loading logo override

All embed widgets also accept design attributes described in WIDGET_DESIGNING.md.


Organization widgets

a-organization-page

Attribute

Purpose

organization

Required organization slug

default-list

Initial tab: resources, services, subscriptions, or packages

view

grid, list, or calendar

calendar-view

day, week, month, or list

start

Initial start date (see Start and End Dates)

end

Initial end date

default-category

Preselect resource category

hide-resource-header

Hide resource headers

hide-organization-header

Hide organization header

hide-organization-filters

Hide filter bar

hide-organization-map

Hide map switch or map area

Important note:

  • In admin, the "calendar board" option maps to calendar-view="list".

a-organization-calendar

Attribute

Purpose

organization

Required organization slug

calendar-view

day, week, month, or list

category

Category slug

start

Initial start date (ISO 8601 only)

end

Initial end date

a-organization-map

Attribute

Purpose

organization

Required organization slug

start

Initial start date (see Start and End Dates)

end

Initial end date

hide-resource-header

Hide resource headers

hide-organization-header

Hide organization header


Resource widgets

a-resource-page

Attribute

Purpose

resource

Required resource slug

service

Preselect service

start

Initial start date (see Start and End Dates)

end

Initial end date

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header

hide-calendar

Hide calendar

a-resource-calendar

Attribute

Purpose

resource

Required resource slug

service

Preselect service

calendar-view

day, week, month, or list

start

Initial start date (ISO 8601 only)

end

Initial end date

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header

a-resource-map

Attribute

Purpose

resource

Required resource slug

service

Preselect service

start

Initial start date (see Start and End Dates)

end

Initial end date

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header

a-resource-booking-panel

Attribute

Purpose

resource

Required resource slug

service

Preselect service

start

Initial start date (see Start and End Dates)

end

Initial end date


Service widgets

a-service-page

Attribute

Purpose

service

Required service slug

resource

Optional resource preselection

a-service-booking-panel

Attribute

Purpose

service

Required service slug

resource

Optional resource preselection

start

Initial start date (see Start and End Dates)

end

Initial end date


Subscription and package widgets

a-subscription-page

Attribute

Purpose

plan

Required plan slug

a-subscription-button

Attribute

Purpose

plan

Required plan slug

label

Trigger label

a-package-page

Attribute

Purpose

package

Required package slug

a-package-button

Attribute

Purpose

package

Required package slug

label

Trigger label


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


Shared modal attributes

Attribute

Purpose

modal-layout

dialog, drawer, or fullscreen

modal-size

sm, md, or lg for dialog layout

modal-width

Custom dialog width, for example 80vw

modal-title

Header title inside modal

close-on-backdrop

Allow close on outside click

show-close-button

Show close button

aria-label

Accessible label for modal dialog


Trigger attributes for entity buttons

Applies to:

  • a-organization-button

  • a-resource-button

  • a-service-button

  • a-subscription-button

  • a-package-button

Attribute

Purpose

label

Default button text

button-width

Trigger width

button-background

Trigger background color

button-text

Trigger text color

a-modal-button is different:

  • no label prop

  • no built-in trigger styling props

  • use your own slotted element 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 non-button element.

<!-- Custom styled button as trigger -->
<a-resource-button
base-url="https://anny.co"
resource="my-resource"
>
<button class="my-cta-button">Book a desk</button>
</a-resource-button>

<!-- Link as trigger -->
<a-organization-button
base-url="https://anny.co"
organization="my-org"
>
<a href="#">Browse availability</a>
</a-organization-button>

<!-- a-modal-button requires a slotted trigger -->
<a-modal-button
base-url="https://anny.co"
resource="my-resource"
>
<button>Open booking</button>
</a-modal-button>

When a slot is provided, the label, button-background, button-text, and button-width trigger attributes are ignored. The click and keyboard handling is still managed by the widget wrapper.

a-resource-button

Attribute

Purpose

resource

Required resource slug

service

Optional service preselection

start

Initial start date (see Start and End Dates)

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header

a-service-button

Attribute

Purpose

service

Required service slug

resource

Optional resource preselection

a-organization-button

Attribute

Purpose

organization

Required organization slug

default-list

Initial organization tab

view

grid, list, or calendar

calendar-view

day, week, month, or list

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header

a-modal-button

Use this for a hand-written modal trigger when you do not want an entity-specific button component.

Attribute

Purpose

resource

Open a resource booking page

service

Preselect service when used with resource

organization

Open organization explore page

default-list

Initial organization tab

view

Initial organization view

calendar-view

Initial organization calendar view

hide-resource-header

Hide resource header

hide-organization-header

Hide organization header


Utility widgets

a-cart-modal-button

Attribute

Purpose

label

Button label

aria-label

Accessible dialog label

modal-layout

dialog, drawer, or fullscreen

modal-size

Dialog size preset

modal-width

Custom dialog width

modal-title

Modal header title

close-on-backdrop

Close on outside click

show-close-button

Show close button

button-width

Trigger width

button-height

Trigger height

button-background

Trigger background

button-text

Trigger text/icon color

show-icon

Show or hide cart icon

a-login-button

Attribute

Purpose

locale

Login button locale

idp-uuid

SSO provider UUID

button-width

Trigger width

button-height

Trigger height

button-background

Trigger background

button-text

Trigger text/icon color

small-border-radius

Trigger border radius

show-icon

Show or hide icon

a-my-bookings

Attribute

Purpose

placeholder-title

Loading placeholder text

base-url

Required

locale

Optional locale

height

Fixed height

fullscreen

Full viewport height

nav-height

Header offset for fullscreen

entity-id

SSO entity ID

idp-uuid

SSO provider UUID

Important note:

  • a-my-bookings always requires authentication. It does not expose should-login because login is mandatory.


Relative Date Shortcuts

Where start or end is supported, relative values can be used.

Supported values:

  • today

  • tomorrow

  • this_week

  • next_week

  • this_month

  • next_month

Example:

<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
start="next_week"
></a-resource-booking-panel>

Practical Recommendations

  • Use the admin-generated snippet first, then refine manually only if needed.

  • Use page widgets for dedicated booking pages.

  • Use panels for custom editorial pages around the booking flow.

  • Use button widgets when booking should open on demand.

  • Put a-login-button and a-cart-modal-button in stable shared UI positions so users can always find them.

  • Prefer drawer for desktop side-panel checkout flows and fullscreen for mobile-first experiences.

Did this answer your question?