Skip to content

postMessage-Kommunikation

Die Kommunikation zwischen WebKatalog und Elternseite erfolgt über das HTML postMessage-API.

Übersicht

Der WebKatalog verwendet den PostMessageService (src/app/core/services/postmessage/postmessage.service.ts) für alle postMessage-Operationen. Dies ermöglicht eine vollständige Lead-Shop-Integration.

Funktionsweise

mermaid
sequenceDiagram
    participant Parent as Elternseite
    participant WK as WebKatalog
    
    WK->>Parent: webkatalog-loaded (beim Laden)
    WK->>Parent: USER_TRACKING (bei Aktionen)
    WK->>Parent: ARTICLE_ADDED / REMOVED
    WK->>Parent: BASKET_UPDATED
    WK->>Parent: CONTACT_REQUEST (Lead)
    WK->>Parent: CURRENT_ARTICLE (auf Anfrage)
    WK->>Parent: ERROR (bei Fehlern)
    
    Parent->>WK: PING_WEBKATALOG (Health-Check)
    Parent->>WK: SET_CONFIG (Live-Updates)
    Parent->>WK: SET_ARTICLE (Artikel setzen)
    Parent->>WK: REQUEST_CURRENT_ARTICLE (aktuellen Artikel abfragen)
    Parent->>WK: SET_THEME (Theme synchronisieren)

Event-Typen

Outbound-Events (WebKatalog → Elternseite)

EventBeschreibung
webkatalog-loadedApp wurde geladen
USER_TRACKINGBenutzerinteraktionen
CONTACT_REQUESTKontaktanfrage / Lead
ARTICLE_ADDEDArtikel zur Planung hinzugefügt
ARTICLE_REMOVEDArtikel aus Planung entfernt
BASKET_UPDATEDWarenkorb aktualisiert
PROPERTY_UPDATE_STARTEDKonfigurationsupdate gestartet
PROPERTY_UPDATEDKonfiguration aktualisiert
PROPERTY_UPDATE_FAILEDKonfigurationsupdate fehlgeschlagen
CONFIGURATION_CHANGEDKonfigurationsänderungen
CURRENT_ARTICLEAktueller Artikel (Response)
ERRORFehlerereignisse

Inbound-Events (Elternseite → WebKatalog)

EventBeschreibung
PING_WEBKATALOGHealth-Check / Bereitschafts-Ping
SET_CONFIGLive-Updates (Preisanzeige, Rabatt)
SET_ARTICLEExternen Artikel setzen
PROPERTY_UPDATEDAlias für SET_ARTICLE (Konfigurationsupdate)
REQUEST_CURRENT_ARTICLEAktuellen Artikel abfragen
SET_THEMETheme synchronisieren

Event-Empfang (Elternseite)

Grundeinrichtung

javascript
window.addEventListener('message', (event) => {
  // Herkunft prüfen (empfohlen)
  const allowedOrigin = 'https://web.3doffice.de';
  if (event.origin !== allowedOrigin) {
    return;
  }
  
  const data = event.data;
  
  if (!data || typeof data.type !== 'string') {
    return;
  }
  
  switch (data.type) {
    case 'webkatalog-loaded':
      console.log('WebKatalog geladen');
      break;
      
    case 'USER_TRACKING':
      console.log('Tracking:', data.action, data);
      break;
      
    case 'CONTACT_REQUEST':
      handleContactRequest(data);
      break;
      
    case 'ERROR':
      console.error('Fehler:', data.errorMessage);
      break;
  }
});

Event-Referenz

webkatalog-loaded

Wird gesendet, sobald der WebKatalog vollständig geladen und bereit ist.

javascript
{
  type: 'webkatalog-loaded',
  timestamp: '2024-01-15T10:30:00.000Z'
}

USER_TRACKING

Sendet Benutzerinteraktionen für Analytics-Zwecke.

Event-Struktur:

javascript
{
  type: 'USER_TRACKING',
  action: 'article_select',
  articleId: '12345',
  articleName: 'Rechtecktisch 160x80',
  category: 'Tische',
  value: 599.00,
  timestamp: '2024-01-15T10:30:00.000Z'
}

Unterstützte Aktionen:

ActionBeschreibungZusätzliche Daten
page_viewSeite wurde aufgerufen-
article_selectArtikel ausgewähltarticleId, articleName
article_configureArtikel konfiguriertarticleId, articleName
article_add_to_cartIn den WarenkorbarticleId, articleName, value
article_add_to_wishlistAuf MerkzettelarticleId, articleName
property_changeEigenschaft geändertarticleId, category
view_3d3D-Ansicht geöffnetarticleId
view_arAR-Ansicht geöffnetarticleId
download_pdfPDF heruntergeladenarticleId
download_cadCAD-Datei heruntergeladenarticleId
share_articleArtikel geteiltarticleId
searchSuche durchgeführt-
filterFilter angewendetcategory
sortSortierung geändert-
navigationNavigation verwendet-

CONTACT_REQUEST

Wird beim Klick auf den "Anfrage senden"-Button gesendet (Lead-Generierung).

Event-Struktur:

javascript
{
  type: 'CONTACT_REQUEST',
  article: {
    id: '12345',
    name: 'Rechtecktisch 160x80',
    manufacturer: 'Hersteller',
    series: 'Serie A',
    configuration: 'Breite: 1600mm, Tiefe: 800mm, Farbe: Weiß',
    price: 599.00,
    currency: 'EUR'
  },
  user: {
    name: 'Max Mustermann',
    email: 'max@example.com',
    phone: '+49 123 456789'
  },
  message: 'Ich hätte gerne ein Angebot für diesen Tisch.',
  timestamp: '2024-01-15T10:30:00.000Z'
}

Kontaktanfrage verarbeiten

javascript
function handleContactRequest(event) {
  const { article, user, message } = event;
  
  // Artikel-Daten
  console.log('Angefragter Artikel:', article.name);
  console.log('Konfiguration:', article.configuration);
  console.log('Preis:', article.price, article.currency);
  
  // Kundendaten
  console.log('Kunde:', user.name);
  console.log('E-Mail:', user.email);
  console.log('Telefon:', user.phone);
  
  // Nachricht
  console.log('Nachricht:', message);
  
  // Hier: Eigene Kontaktformular-Logik implementieren
  // z.B. an CRM-System weiterleiten
}

Hinweis

Der WebKatalog enthält kein eigenes Kontaktformular. Sie müssen das Formular auf Ihrer Website implementieren und die Daten aus dem postMessage-Event vorab ausfüllen.


ARTICLE_ADDED / ARTICLE_REMOVED

Benachrichtigt über Änderungen in der Planung.

ARTICLE_ADDED:

javascript
{
  type: 'ARTICLE_ADDED',
  article: {
    id: '12345',
    name: 'Rechtecktisch 160x80',
    manufacturer: 'Hersteller',
    series: 'Serie A',
    configuration: 'Breite: 1600mm, Tiefe: 800mm'
  },
  timestamp: '2024-01-15T10:30:00.000Z'
}

ARTICLE_REMOVED:

javascript
{
  type: 'ARTICLE_REMOVED',
  article: {
    id: '12345',
    name: 'Rechtecktisch 160x80',
    manufacturer: 'Hersteller',
    series: 'Serie A'
  },
  timestamp: '2024-01-15T10:30:00.000Z'
}

BASKET_UPDATED

Aktualisiert den Warenkorb-Status.

javascript
{
  type: 'BASKET_UPDATED',
  items: [
    {
      id: '12345',
      name: 'Rechtecktisch 160x80',
      quantity: 1,
      price: 599.00
    },
    {
      id: '67890',
      name: 'Stuhl Comfort',
      quantity: 4,
      price: 149.00
    }
  ],
  totalItems: 5,
  timestamp: '2024-01-15T10:30:00.000Z'
}

PROPERTY_UPDATE / PROPERTY_UPDATE_STARTED / PROPERTY_UPDATE_FAILED

Benachrichtigt über Konfigurationsänderungen.

PROPERTY_UPDATE_STARTED:

javascript
{
  type: 'PROPERTY_UPDATE_STARTED',
  timestamp: '2024-01-15T10:30:00.000Z'
}

PROPERTY_UPDATED:

javascript
{
  type: 'PROPERTY_UPDATED',
  article: {
    id: '12345',
    // ... vollständiger Artikel
  },
  timestamp: '2024-01-15T10:30:00.000Z'
}

PROPERTY_UPDATE_FAILED:

javascript
{
  type: 'PROPERTY_UPDATE_FAILED',
  reason: 'Ungültige Konfigurationskombination',
  context: 'PROPERTY_COLOR',
  errorMessage: 'Diese Farbe ist für dieses Modell nicht verfügbar.',
  timestamp: '2024-01-15T10:30:00.000Z'
}

CONFIGURATION_CHANGED

javascript
{
  type: 'CONFIGURATION_CHANGED',
  articleId: '12345',
  changes: [
    {
      property: 'Breite',
      oldValue: '1400mm',
      newValue: '1600mm'
    },
    {
      property: 'Farbe',
      oldValue: 'Weiß',
      newValue: 'Eiche'
    }
  ],
  timestamp: '2024-01-15T10:30:00.000Z'
}

CURRENT_ARTICLE

javascript
{
  type: 'CURRENT_ARTICLE',
  article: {
    id: '12345',
    // ... vollständiger Artikel
  },
  timestamp: '2024-01-15T10:30:00.000Z'
}

ERROR

javascript
{
  type: 'ERROR',
  errorCode: 'CONFIG_001',
  errorMessage: 'Die angeforderte Konfiguration ist nicht verfügbar.',
  context: 'CONFIG_LOAD',
  recoverable: true,
  timestamp: '2024-01-15T10:30:00.000Z'
}

Fehlercodes:

CodeBeschreibungBehebbar
CONFIG_001Konfiguration nicht verfügbarrecoverable: true
CONFIG_002Ungültige Konfigurationskombinationrecoverable: true
LOAD_001Artikel konnte nicht geladen werdenrecoverable: true
LOAD_002Authentifizierung fehlgeschlagenrecoverable: false
NETWORK_001Netzwerkfehlerrecoverable: true

Nachrichten an den WebKatalog (SET_CONFIG)

Sie können Live-Updates an den WebKatalog senden:

javascript
iframe.contentWindow.postMessage(
  {
    type: 'SET_CONFIG',
    showPrice: false,
    discount: 10
  },
  'https://web.3doffice.de'
);

Unterstützte Konfigurationsoptionen:

OptionTypBeschreibung
showPriceboolean | stringPreisanzeige ein/aus. Akzeptiert true/false oder "true"/"false"
discountnumber | stringRabatt in Prozent (0-100). Akzeptiert Zahl oder String

Sicherheit

Verwenden Sie für die Origin-Prüfung immer die vollständige Domain (https://web.3doffice.de) anstatt *.


PING_WEBKATALOG

Health-Check / Bereitschafts-Ping. Der WebKatalog antwortet mit webkatalog-loaded.

javascript
iframe.contentWindow.postMessage('PING_WEBKATALOG', 'https://web.3doffice.de');

Response: Der WebKatalog sendet webkatalog-loaded zurück.


SET_ARTICLE

Setzt einen externen Artikel im WebKatalog. Der Artikel wird neu geladen und in der 3D-Ansicht gerendert.

javascript
iframe.contentWindow.postMessage(
  {
    type: 'SET_ARTICLE',
    article: {
      id: '12345',
      manufacturer: 'Hersteller',
      program: 'Serie A',
      basearticlenumber: 'ABC-123',
      // ... vollständiger IArticle
    }
  },
  'https://web.3doffice.de'
);

Hinweis: PROPERTY_UPDATED ist ein Alias für SET_ARTICLE und kann synonym verwendet werden.


REQUEST_CURRENT_ARTICLE

Fragt den aktuell ausgewählten Artikel vom WebKatalog ab.

javascript
iframe.contentWindow.postMessage(
  {
    type: 'REQUEST_CURRENT_ARTICLE'
  },
  'https://web.3doffice.de'
);

Response: Der WebKatalog antwortet mit CURRENT_ARTICLE.


SET_THEME

Synchronisiert das Theme der Elternseite mit dem WebKatalog.

javascript
iframe.contentWindow.postMessage(
  {
    type: 'SET_THEME',
    theme: 'dark'  // oder 'light'
  },
  'https://web.3doffice.de'
);

Alternativ mit darkmode Boolean:

javascript
iframe.contentWindow.postMessage(
  {
    type: 'SET_THEME',
    darkmode: true
  },
  'https://web.3doffice.de'
);

PostMessageService API

Der PostMessageService kann auch direkt in Angular-Komponenten injiziert werden:

Methoden

MethodeBeschreibung
isEnabled()Prüft ob postMessage aktiv ist (iframe-Kontext)
setParentOrigin(origin)Setzt die erlaubte Parent-Origin für Sicherheit
registerCurrentArticleProvider(fn)Registriert Callback für aktuellen Artikel
registerArticleUpdateHandler(fn)Registriert Handler für SET_ARTICLE-Events
registerThemeHandler(fn)Registriert Handler für SET_THEME-Events

Tracking-Methoden

MethodeBeschreibung
trackUserAction(action, data?)Allgemeines Tracking
trackArticleSelect(article)Artikel-Auswahl tracken
trackArticleConfigure(article)Artikel-Konfiguration tracken
trackAddToCart(article, price?)Warenkorb-Addition tracken
trackAddToWishlist(article)Merkzettel-Addition tracken
trackPropertyChange(id, name, value)Eigenschaftsänderung tracken

Benachrichtigungs-Methoden

MethodeBeschreibung
notifyLoaded()webkatalog-loaded senden
notifyCurrentArticle(article)CURRENT_ARTICLE senden
notifyArticleAdded(article)ARTICLE_ADDED senden
notifyArticleRemoved(article)ARTICLE_REMOVED senden
notifyBasketUpdated(items)BASKET_UPDATED senden
notifyConfigurationChanged(id, changes)CONFIGURATION_CHANGED senden
notifyPropertyUpdateStarted()PROPERTY_UPDATE_STARTED senden
notifyPropertyUpdated(article)PROPERTY_UPDATED senden
notifyPropertyUpdateFailed(reason, context?)PROPERTY_UPDATE_FAILED senden
notifyError(message, options?)ERROR senden
sendContactRequest(article, user?, message?)CONTACT_REQUEST senden

Beispiel: Direkte Nutzung im Service

typescript
import { PostMessageService } from 'src/app/core/services/postmessage/postmessage.service';

@Component({...})
export class MyComponent {
  private readonly postMessageService = inject(PostMessageService);

  onArticleSelected(article: IArticle) {
    // Tracking
    this.postMessageService.trackArticleSelect(article);
    
    // Benachrichtigung
    this.postMessageService.notifyArticleAdded(article);
  }
  
  onError(message: string) {
    this.postMessageService.notifyError(message, {
      code: 'CUSTOM_ERROR',
      recoverable: true
    });
  }
}

Sicherheit

Origin-Validierung

Standardmäßig akzeptiert der WebKatalog Nachrichten von beliebigen Origins ("*"). Für Produktivumgebungen sollte die Parent-Origin explizit gesetzt werden:

typescript
// Im WebKatalog
const postMessageService = inject(PostMessageService);
postMessageService.setParentOrigin('https://ihre-domain.de');

Empfangsseitige Prüfung (Elternseite)

javascript
window.addEventListener('message', (event) => {
  // Origin prüfen
  if (event.origin !== 'https://web.3doffice.de') {
    return;
  }
  
  // Nachricht verarbeiten
  // ...
});

Komplettes Beispiel

javascript
class WebKatalogIntegration {
  constructor(iframeSelector) {
    this.iframe = document.querySelector(iframeSelector);
    this.setupListener();
  }
  
  setupListener() {
    window.addEventListener('message', (event) => {
      // Origin-Prüfung
      if (event.origin !== 'https://web.3doffice.de') {
        return;
      }
      
      this.handleMessage(event.data);
    });
  }
  
  handleMessage(data) {
    if (!data?.type) return;
    
    switch (data.type) {
      case 'webkatalog-loaded':
        this.onLoaded();
        break;
        
      case 'USER_TRACKING':
        this.trackEvent(data.action, data);
        break;
        
      case 'CONTACT_REQUEST':
        this.openContactForm(data);
        break;
        
      case 'ARTICLE_ADDED':
        this.updateBasketCount(data);
        break;
        
      case 'BASKET_UPDATED':
        this.syncBasket(data.items);
        break;
        
      case 'ERROR':
        this.handleError(data);
        break;
    }
  }
  
  onLoaded() {
    console.log('WebKatalog ist bereit');
  }
  
  trackEvent(action, data) {
    // Analytics-Integration
    console.log(`Event: ${action}`, data);
  }
  
  openContactForm(data) {
    // Kontaktformular öffnen und Daten vorab ausfüllen
    console.log('Lead:', data.article);
  }
  
  updateBasketCount(data) {
    console.log('Artikel hinzugefügt:', data.article.name);
  }
  
  syncBasket(items) {
    console.log('Warenkorb aktualisiert:', items.length, 'Artikel');
  }
  
  handleError(data) {
    console.error('WebKatalog Fehler:', data.errorMessage);
  }
}

// Initialisierung
const integration = new WebKatalogIntegration('iframe[name="webkatalog"]');

3D office WebKatalog 2.5 — ub.unitel GmbH