> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anny.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Widget Einbettung - Advanced

> Dieser Leitfaden erklärt, wie du Layout, Events, Modal-Verhalten und HTML-Attribute gezielt steuerst.

## HTML-Seitenstruktur

Minimale Seitenstruktur mit Header, optionaler Sidebar und einem Widget im Hauptbereich.

```html theme={null}
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Meine Buchungsseite</title>
  <script src="https://cdn.anny.co/widget/annyComponents.umd.latest.min.js"></script>
</head>
<body>

  <header>
    <a href="/">Dein 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><!-- optionale Sidebar --></aside>

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

      <!-- weiterer Seiteninhalt -->
    </div>
  </main>

</body>
</html>
```

* Das Script wird einmal im `<head>` geladen.
* `a-login-button` und `a-cart-modal-button` gehören in den Header, damit sie auf allen Seiten sichtbar bleiben.
* Ersetze das Panel durch ein Seiten-Widget mit `fullscreen="true"` und `nav-height`, wenn die Buchung die gesamte Viewport-Höhe füllen soll (siehe [Ganzseitige Widgets](#ganzseitige-widgets) weiter unten).

## Ganzseitige Widgets

Seiten-Widgets eignen sich, wenn das Widget den Hauptinhalt der Seite darstellt.

Seiten-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`

## Empfohlene Integration für ganzseitige Layouts

Verwende `fullscreen="true"`, damit das Widget die verfügbare Viewport-Höhe ausfüllt. Wenn deine Website einen festen Header hat, übergib zusätzlich `nav-height`, damit das Widget nicht darunter gerendert wird.

```html theme={null}
<a-resource-calendar
  base-url="https://anny.co"
  resource="my-resource"
  fullscreen="true"
  nav-height="72px"
></a-resource-calendar>
```

Hinweise:

* `fullscreen="true"` entspricht `height: 100vh`.
* `nav-height` ändert das auf `calc(100vh - nav-height)`.
* Wenn du `height` setzt, wird die automatische Größenanpassung deaktiviert und der iframe hat eine feste Höhe.
* Für `*-page`, Map-, Kalender- und `a-my-bookings`-Widgets sind ganzseitige Layouts in der Regel die sauberste Integration.

## Organization-Map und Organization-Kalender

Diese sind Seiten-Widgets, keine Modal-Buttons. Behandle sie wie einen vollständigen Seitenbereich.

```html theme={null}
<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>
```

Verwende die Organization-Map, wenn die Karte die primäre Benutzeroberfläche ist. Verwende den Organization-Kalender, wenn die Verfügbarkeitsnavigation im Vordergrund steht. Wenn du stattdessen den vollständigen Explore-Flow möchtest, nimm `a-organization-page`.

## Panels

Booking-Panels sind bewusst kompakt gehalten und sperren die Navigation.

Panel-Widgets:

* `a-resource-booking-panel`
* `a-service-booking-panel`

Wichtiges Verhalten:

* Panels verwenden immer dynamische Höhe.
* Externe `height`- und `fullscreen`-Werte werden ignoriert.
* Panels sind dazu gedacht, den Buchungsfluss in dein eigenes Seitenlayout einzubetten.

```html theme={null}
<a-service-booking-panel
  base-url="https://anny.co"
  service="intro-call"
></a-service-booking-panel>
```

## Login-Button und Warenkorb-Button

Diese zwei Komponenten werden unter Organisation → Einstellungen → Buchungsseite → Globale Komponenten konfiguriert. Sie sind als gemeinsame Steuerelemente gedacht, die sich in der Regel im Site-Header oder in einer fixen Navigationsleiste befinden.

### Login-Button

Verwende `a-login-button`, wenn du ein gemeinsames Login/Logout-Element benötigst, das mit der Widget-Session synchron bleibt.

```html theme={null}
<a-login-button
  base-url="https://anny.co"
  locale="de"
  idp-uuid="your-idp-uuid"
></a-login-button>
```

Verhalten:

* Lädt einen eigenen Login-iframe.
* Wechselt automatisch in den eingeloggten Avatar-Zustand.
* Sendet Auth-Änderungen weiter, damit benachbarte Widgets ihren Authentifizierungszustand aktualisieren.

Gute Platzierungen:

* Haupt-Site-Header
* Mobile Navigation Drawer
* Obere Leiste auf Buchungs-Landingpages

### Warenkorb-Button

Verwende `a-cart-modal-button`, wenn Nutzer Artikel aus Booking-Widgets hinzufügen und später auschecken sollen.

```html theme={null}
<a-cart-modal-button
  base-url="https://anny.co"
  modal-layout="drawer"
  label="Warenkorb"
></a-cart-modal-button>
```

Verhalten:

* Zeigt eine Live-Badge mit der Artikelanzahl.
* Bleibt mit benachbarten Widgets auf derselben Seite synchron.
* Öffnet den Checkout in einem Modal-Overlay.

Häufige Kombinationen:

* `a-resource-booking-panel` zusammen mit `a-cart-modal-button`
* Mehrere Booking-Widgets auf einer Seite mit einem gemeinsamen Warenkorb-Button

## Events und Tracking

Die meisten Embed-Widgets leiten Buchungs-Lifecycle-Events als DOM Custom Events weiter. Trifft für alles aus den Login-Button zu.

Unterstützte Event-Namen:

* `view-page`
* `add-to-cart`
* `start-checkout`
* `complete-checkout`

Häufige Felder im Event-Payload:

* `event_name`
* `value`
* `gross_value`
* `tax`
* `currency`
* `transaction_id`
* `items`

Beispiel:

```html theme={null}
<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 abgeschlossen', data.transaction_id, data.gross_value, data.currency)
  })
</script>
```

GA4-Beispiel:

```html theme={null}
<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>
```

Hinweise:

* `a-login-button` und `a-cart-modal-button` sind Hilfs-Widgets und senden keine Buchungs-Events.
* Seiten-Widgets, Maps, Kalender, Booking-Panels und checkout-orientierte Seiten senden Buchungs-Events.
* Subscription- und Package-Widgets senden checkout-fokussierte Events. In der Praxis sind `view-page`, `start-checkout` und `complete-checkout` die relevantesten.

### UTM-Parameter und Click-IDs

Für Attribution musst du nichts weiter tun. Wenn ein Widget lädt, liest es den Query-String der **übergeordneten Seiten-URL** aus und leitet diese Parameter automatisch in den eingebetteten iframe weiter:

| Parameter                                                             | Plattform                     |
| --------------------------------------------------------------------- | ----------------------------- |
| `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term` | Alle (Google Analytics u. a.) |
| `gclid`                                                               | Google Ads                    |
| `fbclid`                                                              | Meta / Facebook Ads           |
| `ttclid`                                                              | TikTok Ads                    |
| `li_fat_id`                                                           | LinkedIn Ads                  |

Wenn ein Nutzer also über `?utm_campaign=fruehling&gclid=abc123` auf deine Seite kommt, trägt das Widget diese Werte durch den gesamten Buchungsfluss – Conversion-Tracking funktioniert ohne zusätzliche Konfiguration.

Es ist kein HTML-Attribut erforderlich – die Weiterleitung erfolgt automatisch bei jedem Widget-Ladevorgang.

## Start- und Enddatum

Die meisten Widgets akzeptieren `start` (und manchmal `end`), um Kalender oder Karte auf einen bestimmten Datumsbereich vorzunavigieren.

**ISO-8601-Datumsstring** – exaktes Datum:

```html theme={null}
<a-resource-page
  base-url="https://anny.co"
  resource="my-resource"
  start="2025-06-15"
></a-resource-page>
```

**Relativer Schlüsselwert** – wird zum Render-Zeitpunkt aufgelöst:

| Wert         | Bedeutung                   |
| ------------ | --------------------------- |
| `today`      | Aktueller Tag               |
| `tomorrow`   | Nächster Tag                |
| `this_week`  | Beginn der aktuellen Woche  |
| `next_week`  | Beginn der nächsten Woche   |
| `this_month` | Beginn des aktuellen Monats |
| `next_month` | Beginn des nächsten Monats  |

```html theme={null}
<a-resource-booking-panel
  base-url="https://anny.co"
  resource="my-resource"
  start="tomorrow"
></a-resource-booking-panel>
```

Relative Werte werden überall unterstützt – **außer** bei `a-resource-calendar` und `a-organization-calendar`, die ISO 8601 erfordern.

`end` erwartet immer einen ISO-8601-Datumsstring.

## Anpassungsoptionen nach Widget-Typ

Dieser Abschnitt dokumentiert die öffentlichen HTML-Attribute. Admin-generierte Snippets decken in der Regel die wichtigsten davon bereits ab.

### Gemeinsame Attribute für Embed-Widgets

Gilt für Seiten-Widgets und Panel-Widgets. Nicht anwendbar auf Button-Widgets.

| Attribut       | Zweck                                                                                                                 |
| -------------- | --------------------------------------------------------------------------------------------------------------------- |
| `base-url`     | Erforderlich. anny-Basis-URL, z. B. `https://anny.co`                                                                 |
| `locale`       | Widget-Sprache erzwingen. Wird es weggelassen, wird die Browser-Sprache verwendet                                     |
| `height`       | Feste iframe-Höhe, z. B. `700px` oder `80vh`. Deaktiviert die automatische Größenanpassung. Nicht für Button-Widgets. |
| `fullscreen`   | Viewport-Höhe füllen (`100vh`). Nicht für Button-Widgets.                                                             |
| `nav-height`   | Abstand vom Viewport-Rand bei `fullscreen`, z. B. `64px`                                                              |
| `should-login` | Login vor der Buchung erforderlich                                                                                    |
| `idp-uuid`     | UUID des SSO-Identity-Providers                                                                                       |
| `logo-url`     | Eigenes Logo für die Lade-Animation                                                                                   |

Alle Embed-Widgets akzeptieren zusätzlich die Design-Attribute aus `WIDGET_DESIGNING.md`.

## Organization-Widgets

### `a-organization-page`

| Attribut                    | Zweck                                                                    |
| --------------------------- | ------------------------------------------------------------------------ |
| `organization`              | Erforderlicher Organization-Slug                                         |
| `default-list`              | Initialer Tab: `resources`, `services`, `subscriptions` oder `packages`  |
| `view`                      | `grid`, `list` oder `calendar`                                           |
| `calendar-view`             | `day`, `week`, `month` oder `list`                                       |
| `start`                     | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`                       | Initiales Enddatum                                                       |
| `default-category`          | Ressourcenkategorie vorauswählen                                         |
| `hide-resource-header`      | Ressource-Header ausblenden                                              |
| `hide-organization-header`  | Organization-Header ausblenden                                           |
| `hide-organization-filters` | Filterleiste ausblenden                                                  |
| `hide-organization-map`     | Karten-Umschalter ausblenden                                             |

Hinweis:

* Die Option „Kalender-Board" im Admin entspricht `calendar-view="list"`.

### `a-organization-calendar`

| Attribut        | Zweck                               |
| --------------- | ----------------------------------- |
| `organization`  | Erforderlicher Organization-Slug    |
| `calendar-view` | `day`, `week`, `month` oder `list`  |
| `category`      | Kategorie-Slug                      |
| `start`         | Initiales Startdatum (nur ISO 8601) |
| `end`           | Initiales Enddatum                  |

### `a-organization-map`

| Attribut                   | Zweck                                                                    |
| -------------------------- | ------------------------------------------------------------------------ |
| `organization`             | Erforderlicher Organization-Slug                                         |
| `start`                    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`                      | Initiales Enddatum                                                       |
| `hide-resource-header`     | Ressource-Header ausblenden                                              |
| `hide-organization-header` | Organization-Header ausblenden                                           |

## Ressource-Widgets

### `a-resource-page`

| Attribut                   | Zweck                                                                    |
| -------------------------- | ------------------------------------------------------------------------ |
| `resource`                 | Erforderlicher Ressource-Slug                                            |
| `service`                  | Service vorauswählen                                                     |
| `start`                    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`                      | Initiales Enddatum                                                       |
| `hide-resource-header`     | Ressource-Header ausblenden                                              |
| `hide-organization-header` | Organization-Header ausblenden                                           |
| `hide-calendar`            | Kalender ausblenden                                                      |

### `a-resource-calendar`

| Attribut                   | Zweck                               |
| -------------------------- | ----------------------------------- |
| `resource`                 | Erforderlicher Ressource-Slug       |
| `service`                  | Service vorauswählen                |
| `calendar-view`            | `day`, `week`, `month` oder `list`  |
| `start`                    | Initiales Startdatum (nur ISO 8601) |
| `end`                      | Initiales Enddatum                  |
| `hide-resource-header`     | Ressource-Header ausblenden         |
| `hide-organization-header` | Organization-Header ausblenden      |

### `a-resource-map`

| Attribut                   | Zweck                                                                    |
| -------------------------- | ------------------------------------------------------------------------ |
| `resource`                 | Erforderlicher Ressource-Slug                                            |
| `service`                  | Service vorauswählen                                                     |
| `start`                    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`                      | Initiales Enddatum                                                       |
| `hide-resource-header`     | Ressource-Header ausblenden                                              |
| `hide-organization-header` | Organization-Header ausblenden                                           |

### `a-resource-booking-panel`

| Attribut   | Zweck                                                                    |
| ---------- | ------------------------------------------------------------------------ |
| `resource` | Erforderlicher Ressource-Slug                                            |
| `service`  | Service vorauswählen                                                     |
| `start`    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`      | Initiales Enddatum                                                       |

## Service-Widgets

### `a-service-page`

| Attribut   | Zweck                            |
| ---------- | -------------------------------- |
| `service`  | Erforderlicher Service-Slug      |
| `resource` | Optionale Ressource vorauswählen |

### `a-service-booking-panel`

| Attribut   | Zweck                                                                    |
| ---------- | ------------------------------------------------------------------------ |
| `service`  | Erforderlicher Service-Slug                                              |
| `resource` | Optionale Ressource vorauswählen                                         |
| `start`    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `end`      | Initiales Enddatum                                                       |

## Subscription- und Package-Widgets

### `a-subscription-page`

| Attribut | Zweck                    |
| -------- | ------------------------ |
| `plan`   | Erforderlicher Plan-Slug |

### `a-subscription-button`

| Attribut | Zweck                            |
| -------- | -------------------------------- |
| `plan`   | Erforderlicher Plan-Slug         |
| `label`  | Beschriftung des Trigger-Buttons |

### `a-package-page`

| Attribut  | Zweck                       |
| --------- | --------------------------- |
| `package` | Erforderlicher Package-Slug |

### `a-package-button`

| Attribut  | Zweck                            |
| --------- | -------------------------------- |
| `package` | Erforderlicher Package-Slug      |
| `label`   | Beschriftung des Trigger-Buttons |

## Button-Widgets

Gilt für:

* `a-organization-button`
* `a-resource-button`
* `a-service-button`
* `a-subscription-button`
* `a-package-button`
* `a-modal-button`
* `a-cart-modal-button`

## Gemeinsame Modal-Attribute

| Attribut            | Zweck                                          |
| ------------------- | ---------------------------------------------- |
| `modal-layout`      | `dialog`, `drawer` oder `fullscreen`           |
| `modal-size`        | `sm`, `md` oder `lg` für Dialog-Layout         |
| `modal-width`       | Benutzerdefinierte Dialog-Breite, z. B. `80vw` |
| `modal-title`       | Titel im Modal-Header                          |
| `close-on-backdrop` | Schließen per Klick außerhalb erlauben         |
| `show-close-button` | Schließen-Button anzeigen                      |
| `aria-label`        | Barrierefreies Label für den Modal-Dialog      |

## Trigger-Attribute für Entity-Buttons

Gilt für:

* `a-organization-button`
* `a-resource-button`
* `a-service-button`
* `a-subscription-button`
* `a-package-button`

| Attribut            | Zweck                             |
| ------------------- | --------------------------------- |
| `label`             | Standard-Beschriftung des Buttons |
| `button-width`      | Breite des Triggers               |
| `button-background` | Hintergrundfarbe des Triggers     |
| `button-text`       | Textfarbe des Triggers            |

`a-modal-button` ist anders:

* kein `label`-Prop
* keine eingebauten Trigger-Styling-Props
* verwende ein eigenes Element im Slot als Trigger

## Eigener Trigger (Slot)

Alle Button-Widgets akzeptieren einen Standard-Slot, der den eingebauten Trigger ersetzt. Nutze das, wenn du den Trigger selbst gestalten oder ein anderes Element als Button verwenden möchtest.

```html theme={null}
<!-- Eigener Button als Trigger -->
<a-resource-button
  base-url="https://anny.co"
  resource="my-resource"
>
  <button class="my-cta-button">Schreibtisch buchen</button>
</a-resource-button>

<!-- Link als Trigger -->
<a-organization-button
  base-url="https://anny.co"
  organization="my-org"
>
  <a href="#">Verfügbarkeit ansehen</a>
</a-organization-button>

<!-- a-modal-button erfordert immer einen Slot-Trigger -->
<a-modal-button
  base-url="https://anny.co"
  resource="my-resource"
>
  <button>Buchung öffnen</button>
</a-modal-button>
```

Wenn ein Slot verwendet wird, werden `label`, `button-background`, `button-text` und `button-width` ignoriert. Klick- und Tastatursteuerung werden weiterhin vom Widget-Wrapper übernommen.

### `a-resource-button`

| Attribut                   | Zweck                                                                    |
| -------------------------- | ------------------------------------------------------------------------ |
| `resource`                 | Erforderlicher Ressource-Slug                                            |
| `service`                  | Optionaler Service                                                       |
| `start`                    | Initiales Startdatum (siehe [Start- und Enddatum](#start--und-enddatum)) |
| `hide-resource-header`     | Ressource-Header ausblenden                                              |
| `hide-organization-header` | Organization-Header ausblenden                                           |

### `a-service-button`

| Attribut   | Zweck                            |
| ---------- | -------------------------------- |
| `service`  | Erforderlicher Service-Slug      |
| `resource` | Optionale Ressource vorauswählen |

### `a-organization-button`

| Attribut                   | Zweck                              |
| -------------------------- | ---------------------------------- |
| `organization`             | Erforderlicher Organization-Slug   |
| `default-list`             | Initialer Organization-Tab         |
| `view`                     | `grid`, `list` oder `calendar`     |
| `calendar-view`            | `day`, `week`, `month` oder `list` |
| `hide-resource-header`     | Ressource-Header ausblenden        |
| `hide-organization-header` | Organization-Header ausblenden     |

### `a-modal-button`

Verwende diesen Button, wenn du einen eigenen Modal-Trigger ohne entity-spezifische Button-Komponente benötigst.

| Attribut                   | Zweck                                          |
| -------------------------- | ---------------------------------------------- |
| `resource`                 | Ressource-Buchungsseite öffnen                 |
| `service`                  | Service vorauswählen (zusammen mit `resource`) |
| `organization`             | Organization-Explore-Seite öffnen              |
| `default-list`             | Initialer Organization-Tab                     |
| `view`                     | Initiale Organization-Ansicht                  |
| `calendar-view`            | Initiale Organization-Kalenderansicht          |
| `hide-resource-header`     | Ressource-Header ausblenden                    |
| `hide-organization-header` | Organization-Header ausblenden                 |

## Hilfs-Widgets

### `a-cart-modal-button`

| Attribut            | Zweck                                |
| ------------------- | ------------------------------------ |
| `label`             | Button-Beschriftung                  |
| `aria-label`        | Barrierefreies Dialog-Label          |
| `modal-layout`      | `dialog`, `drawer` oder `fullscreen` |
| `modal-size`        | Dialog-Größen-Preset                 |
| `modal-width`       | Benutzerdefinierte Dialog-Breite     |
| `modal-title`       | Titel im Modal-Header                |
| `close-on-backdrop` | Schließen per Klick außerhalb        |
| `show-close-button` | Schließen-Button anzeigen            |
| `button-width`      | Trigger-Breite                       |
| `button-height`     | Trigger-Höhe                         |
| `button-background` | Trigger-Hintergrund                  |
| `button-text`       | Trigger-Text-/Icon-Farbe             |
| `show-icon`         | Icon ein-/ausblenden                 |

### `a-login-button`

| Attribut              | Zweck                     |
| --------------------- | ------------------------- |
| `locale`              | Sprache des Login-Buttons |
| `idp-uuid`            | UUID des SSO-Providers    |
| `button-width`        | Trigger-Breite            |
| `button-height`       | Trigger-Höhe              |
| `button-background`   | Trigger-Hintergrund       |
| `button-text`         | Trigger-Text-/Icon-Farbe  |
| `small-border-radius` | Trigger-Eckenradius       |
| `show-icon`           | Icon ein-/ausblenden      |

### `a-my-bookings`

| Attribut     | Zweck                         |
| ------------ | ----------------------------- |
| `base-url`   | Erforderlich                  |
| `locale`     | Optionale Sprache             |
| `height`     | Feste Höhe                    |
| `fullscreen` | Viewport-Höhe füllen          |
| `nav-height` | Header-Abstand für Fullscreen |
| `idp-uuid`   | UUID des SSO-Providers        |

Hinweis:

* `a-my-bookings` erfordert immer eine Authentifizierung. `should-login` ist nicht verfügbar, da Login obligatorisch ist.

## Empfehlungen

* Nutze zuerst das Admin-generierte Snippet und verfeinere es manuell nur wenn nötig.
* Verwende Seiten-Widgets für dedizierte Buchungsseiten.
* Verwende Panels für redaktionelle Seiten rund um den Buchungsfluss.
* Verwende Button-Widgets, wenn die Buchung erst nach einem Klick sichtbar sein soll.
* Platziere `a-login-button` und `a-cart-modal-button` an stabilen, gut sichtbaren Stellen im UI.
* Bevorzuge `drawer` für Desktop-seitige Checkout-Flows und `fullscreen` für mobile Erlebnisse.
