Skip to content

postMessage communication ​

Communication between the WebKatalog and the parent page uses the HTML postMessage API.

Overview ​

The WebKatalog reports events to the parent page and accepts commands from it; both only when it runs in an iFrame.

How it works ​

mermaid
sequenceDiagram
    participant Parent as Parent page
    participant WK as WebKatalog
    
    WK->>Parent: webkatalog-loaded (on load)
    WK->>Parent: USER_TRACKING (on actions)
    WK->>Parent: ARTICLE_ADDED
    WK->>Parent: BASKET_UPDATED
    WK->>Parent: CURRENT_ARTICLE (on request)
    WK->>Parent: ERROR (on errors)
    
    Parent->>WK: PING_WEBKATALOG (health check)
    Parent->>WK: SET_CONFIG (live updates)
    Parent->>WK: SET_ARTICLE (set article)
    Parent->>WK: REQUEST_CURRENT_ARTICLE (query current article)
    Parent->>WK: SET_THEME (sync theme)

Event types ​

Outbound events (WebKatalog → parent page) ​

EventDescription
webkatalog-loadedApp has loaded
USER_TRACKINGUser interactions
CONTACT_REQUESTContact request / lead (planned)
ARTICLE_ADDEDArticle added to the planning
ARTICLE_REMOVEDArticle removed from the planning (planned)
BASKET_UPDATEDShopping cart updated
PROPERTY_UPDATE_STARTEDConfiguration update started
PROPERTY_UPDATEDConfiguration updated
PROPERTY_UPDATE_FAILEDConfiguration update failed
CONFIGURATION_CHANGEDConfiguration changes (planned)
CURRENT_ARTICLECurrent article (response)
ERRORMessage could not be processed

Inbound events (parent page → WebKatalog) ​

EventDescription
PING_WEBKATALOGHealth check / readiness ping
SET_CONFIGLive updates (price display, discount)
SET_ARTICLESet an external article
PROPERTY_UPDATEDAlias for SET_ARTICLE (configuration update)
REQUEST_CURRENT_ARTICLEQuery the current article
SET_THEMESync theme

Receiving events (parent page) ​

Basic setup ​

javascript
window.addEventListener('message', (event) => {
  // Check origin (recommended)
  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 loaded');
      break;
      
    case 'USER_TRACKING':
      console.log('Tracking:', data.action, data);
      break;
      
    case 'CONTACT_REQUEST':
      handleContactRequest(data);
      break;
      
    case 'ERROR':
      console.error('Error:', data.errorMessage);
      break;
  }
});

Event reference ​

webkatalog-loaded ​

Sent as soon as the WebKatalog has fully loaded and is ready.

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

USER_TRACKING ​

Sends user interactions for analytics purposes.

Event structure:

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

For article_add_to_cart, value (the price) is added.

Actions sent:

ActionDescriptionAdditional data
article_selectArticle selectedarticleId, articleName
article_add_to_cartAdded to the shopping cartarticleId, articleName, value
article_add_to_wishlistAdded to wishlistarticleId, articleName

Planned (not currently sent): page_view, article_configure, property_change, view_3d, view_ar, download_pdf, download_cad, share_article, search, filter, sort, navigation.


CONTACT_REQUEST ​

Planned

Not currently sent.

Intended for contact requests from the WebKatalog (lead generation).

Event structure:

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'
}

Handling a contact request ​

javascript
function handleContactRequest(event) {
  const { article, user, message } = event;
  
  // Article data
  console.log('Requested article:', article.name);
  console.log('Configuration:', article.configuration);
  console.log('Price:', article.price, article.currency);
  
  // Customer data
  console.log('Customer:', user.name);
  console.log('Email:', user.email);
  console.log('Phone:', user.phone);
  
  // Message
  console.log('Message:', message);
  
  // Here: implement your own contact form logic,
  // e.g. forward to a CRM system
}

Note

The WebKatalog does not include a contact form of its own. You need to implement the form on your website and prefill it with the data from the postMessage event.


ARTICLE_ADDED / ARTICLE_REMOVED ​

Notifies about changes in the planning.

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:

Planned

Not currently sent.

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

BASKET_UPDATED ​

Sent on every click on "Add to cart" and contains only that article.

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

PROPERTY_UPDATE / PROPERTY_UPDATE_STARTED / PROPERTY_UPDATE_FAILED ​

Notifies about configuration changes.

PROPERTY_UPDATE_STARTED:

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

PROPERTY_UPDATED:

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

PROPERTY_UPDATE_FAILED:

javascript
{
  type: 'PROPERTY_UPDATE_FAILED',
  reason: 'Beim Aktualisieren des Artikels ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.',
  errorMessage: 'Beim Aktualisieren des Artikels ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.',
  timestamp: '2024-01-15T10:30:00.000Z'
}

reason (and the identical errorMessage) is one of:

  • Text in the language of the WebKatalog (property change failed)
  • 'Missing article id' (SET_ARTICLE without article.id)
  • 'Failed to apply external update' (SET_ARTICLE failed)
  • 'The article was replaced by a newer article load' with context: 'ARTICLE_REPLACED' (see below)

Every PROPERTY_UPDATE_STARTED is followed by exactly one PROPERTY_UPDATED or one PROPERTY_UPDATE_FAILED. A loading indicator on the parent page between the two therefore always ends.

context: 'ARTICLE_REPLACED': While the change was still running, a different article was loaded (catalog click, SET_ARTICLE, reload after SET_CONFIG). The change is discarded and no longer applied to the new article. This is not a server error; the parent page should not show an error message but wait for the ARTICLE_ADDED of the new article.

javascript
{
  type: 'PROPERTY_UPDATE_FAILED',
  reason: 'The article was replaced by a newer article load',
  context: 'ARTICLE_REPLACED',
  errorMessage: 'The article was replaced by a newer article load',
  timestamp: '2024-01-15T10:30:00.000Z'
}

CONFIGURATION_CHANGED ​

Planned

Not currently sent.

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',
    // ... complete article
  },
  timestamp: '2024-01-15T10:30:00.000Z'
}

ERROR ​

Sent when an error occurs while processing a message from the parent page. Unknown or incomplete messages are ignored without a reply.

javascript
{
  type: 'ERROR',
  errorCode: 'MSG_ERROR',
  errorMessage: 'Failed to process message',
  context: 'SET_ARTICLE',   // Type of the message
  timestamp: '2024-01-15T10:30:00.000Z'
}

Messages to the WebKatalog ​

SET_CONFIG ​

Live updates of settings:

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

Supported configuration options:

OptionTypeDescription
showPriceboolean | stringPrice display on/off. Accepts true/false or "true"/"false"
discountnumber | stringDiscount in percent (0-100). Accepts a number or a string

Behavior:

  • showPrice: true (previously off): The current article is reloaded in its current configuration, because the price only comes from the server with an article request. The camera position is kept. A property change in progress is completed first.
  • showPrice: false hides the price immediately, without reloading.
  • discount takes effect immediately: the price tab shows the list price struck through, with "Your price · −X %" below it.

Security

Always use the full domain (https://web.3doffice.de) for the origin check instead of *.


PING_WEBKATALOG ​

Health check / readiness ping. The WebKatalog responds with webkatalog-loaded.

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

Response: The WebKatalog sends back webkatalog-loaded.


SET_ARTICLE ​

Applies the article object sent with the message (e.g. from CURRENT_ARTICLE or PROPERTY_UPDATED) and shows it in the 3D view. The article data is not fetched again from the server; article.id is required.

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

Note: PROPERTY_UPDATED is an alias for SET_ARTICLE and can be used interchangeably.


REQUEST_CURRENT_ARTICLE ​

Queries the currently selected article from the WebKatalog.

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

Response: The WebKatalog responds with CURRENT_ARTICLE.


SET_THEME ​

Syncs the theme of the parent page with the WebKatalog.

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

Alternatively with the darkmode boolean:

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

Security ​

  • The WebKatalog sends its messages to the parent window with target origin *. That is why you should always check event.origin on the parent page.
  • The WebKatalog only processes messages from its direct parent window (event.source === window.parent); there is no origin check.
  • Messages contain article and price data, but never the token.

Receiver-side check (parent page) ​

javascript
window.addEventListener('message', (event) => {
  // Check origin
  if (event.origin !== 'https://web.3doffice.de') {
    return;
  }
  
  // Process message
  // ...
});

Behavior ​

  • webkatalog-loaded arrives once, as soon as the view is ready – not only once an article has loaded. The WebKatalog answers PING_WEBKATALOG with webkatalog-loaded at any time.
  • Send commands only after webkatalog-loaded. Messages that arrive earlier may be lost.
  • Outside an iFrame, the WebKatalog sends nothing.
  • After SET_ARTICLE, the WebKatalog sends back PROPERTY_UPDATED with the new article. PROPERTY_UPDATED is also accepted as input (like SET_ARTICLE) – do not send it back, or you will create a loop.
  • BASKET_UPDATED arrives per click on "Add to cart" and contains only that article (quantity 1); totalItems counts the line items of this article including children.
  • REQUEST_CURRENT_ARTICLE without a loaded article gets no response.

3D office WebKatalog 2.5 — ub.unitel GmbH