Appearance
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)
| Event | Beschreibung |
|---|---|
webkatalog-loaded | App wurde geladen |
USER_TRACKING | Benutzerinteraktionen |
CONTACT_REQUEST | Kontaktanfrage / Lead |
ARTICLE_ADDED | Artikel zur Planung hinzugefügt |
ARTICLE_REMOVED | Artikel aus Planung entfernt |
BASKET_UPDATED | Warenkorb aktualisiert |
PROPERTY_UPDATE_STARTED | Konfigurationsupdate gestartet |
PROPERTY_UPDATED | Konfiguration aktualisiert |
PROPERTY_UPDATE_FAILED | Konfigurationsupdate fehlgeschlagen |
CONFIGURATION_CHANGED | Konfigurationsänderungen |
CURRENT_ARTICLE | Aktueller Artikel (Response) |
ERROR | Fehlerereignisse |
Inbound-Events (Elternseite → WebKatalog)
| Event | Beschreibung |
|---|---|
PING_WEBKATALOG | Health-Check / Bereitschafts-Ping |
SET_CONFIG | Live-Updates (Preisanzeige, Rabatt) |
SET_ARTICLE | Externen Artikel setzen |
PROPERTY_UPDATED | Alias für SET_ARTICLE (Konfigurationsupdate) |
REQUEST_CURRENT_ARTICLE | Aktuellen Artikel abfragen |
SET_THEME | Theme 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:
| Action | Beschreibung | Zusätzliche Daten |
|---|---|---|
page_view | Seite wurde aufgerufen | - |
article_select | Artikel ausgewählt | articleId, articleName |
article_configure | Artikel konfiguriert | articleId, articleName |
article_add_to_cart | In den Warenkorb | articleId, articleName, value |
article_add_to_wishlist | Auf Merkzettel | articleId, articleName |
property_change | Eigenschaft geändert | articleId, category |
view_3d | 3D-Ansicht geöffnet | articleId |
view_ar | AR-Ansicht geöffnet | articleId |
download_pdf | PDF heruntergeladen | articleId |
download_cad | CAD-Datei heruntergeladen | articleId |
share_article | Artikel geteilt | articleId |
search | Suche durchgeführt | - |
filter | Filter angewendet | category |
sort | Sortierung geändert | - |
navigation | Navigation 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:
| Code | Beschreibung | Behebbar |
|---|---|---|
CONFIG_001 | Konfiguration nicht verfügbar | recoverable: true |
CONFIG_002 | Ungültige Konfigurationskombination | recoverable: true |
LOAD_001 | Artikel konnte nicht geladen werden | recoverable: true |
LOAD_002 | Authentifizierung fehlgeschlagen | recoverable: false |
NETWORK_001 | Netzwerkfehler | recoverable: 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:
| Option | Typ | Beschreibung |
|---|---|---|
showPrice | boolean | string | Preisanzeige ein/aus. Akzeptiert true/false oder "true"/"false" |
discount | number | string | Rabatt 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
| Methode | Beschreibung |
|---|---|
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
| Methode | Beschreibung |
|---|---|
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
| Methode | Beschreibung |
|---|---|
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"]');