Skip to main content

Overview

Communication between ClearLine’s Customer-Facing Screen (CFS) and third-party POS systems (e.g., Clover, PAX) is implemented via JavaScript iframe events using the window.postMessage() API. This enables seamless interaction between the CFS application running in an iframe and the parent POS system.

Event Model

All events follow a standardized TypeScript interface:
Event Types
export enum IframeMessageTypes {
  buttonClick = "buttonClick",
  inputFocus = "inputFocus",
  inputBlur = "inputBlur",
  formSubmitted = "formSubmitted",
  userActivity = "userActivity",
  setWindowClass = "setWindowClass",
  scanCompleted = "scanCompleted",
  scanCancelled = "scanCancelled",
  init = "init",
}

interface IframeMessageData<T> {
  type: IframeMessageTypes;
  data: T;
}

Sending Events

Events are sent using the standard postMessage API:
Usage
window.postMessage(params, "*");
The target origin is set to "*" for compatibility across different POS system domains. Implement additional validation in production environments as needed.

Output Events (CFS → POS System)

These events are sent from the CFS application to the external POS system.

init

Triggered when the CFS application completes initialization. This event signals that the CFS is ready to receive messages.
window.postMessage(
  {
    type: "init",
    data: {
      projectName: "cfs",
    },
  },
  "*"
);

Event Data

FieldTypeDescription
projectNamestringStatic string “cfs” – identifies the source project

buttonClick

Emitted when a button is clicked in the CFS application. Commonly used to request external hardware scanner usage (e.g., for customer check-in).
window.postMessage(
  {
    type: "buttonClick",
    data: {
      targetId: "scan",
      buttonId: "scan",
    },
  },
  "*"
);

Event Data

FieldTypeDescription
targetIdstringHTML element ID of the clicked button (e.g., “scan”)
buttonIdstringDeprecated. Legacy support only (use targetId instead).
Use targetId for all new implementations. The buttonId field is maintained for backward compatibility only.

inputFocus

Emitted when an input field in the CFS gains focus. Use this event to notify the external POS to prepare for login or check-in actions.
window.postMessage(
  {
    type: "inputFocus",
    data: {
      targetId: "search",
      inputId: "search",
    },
  },
  "*"
);

Event Data

FieldTypeDescription
targetIdstringHTML element ID of the input field (e.g., “search”)
inputIdstringDeprecated. Legacy support only (use targetId instead).

inputBlur

Emitted when an input field in the CFS loses focus.
window.postMessage(
  {
    type: "inputBlur",
    data: {
      targetId: "search",
      inputId: "search",
    },
  },
  "*"
);

Event Data

FieldTypeDescription
targetIdstringHTML element ID of the input field (e.g., “search”)
inputIdstringDeprecated. Legacy support only (use targetId instead).

Input Events (POS System → CFS)

These events are sent from the external POS system to the CFS application.

formSubmitted

Instructs the CFS to close the current iframe window, typically after a form has been submitted externally (e.g., in a CFS Template iframe).
window.postMessage(
  {
    type: "formSubmitted",
    data: null
  },
  "*"
);

Event Data

No additional parameters required.

userActivity

Used to prolong user activity inside the iframe and prevent inactivity prompts (e.g., “Are you still here?” dialogs).
window.postMessage(
  {
    type: "userActivity",
    data: null
  },
  "*"
);

Event Data

No additional parameters required.

setWindowClass

Previously used to set CSS class on the iframe window.
This event is deprecated and should not be used in new implementations.

scanCompleted

Delivers the result of an external hardware scan (barcode, QR code, username, email). Commonly used for customer login or check-in workflows.
window.postMessage(
  {
    type: "scanCompleted",
    data: "user@example.com"
  },
  "*"
);

Event Data

FieldTypeDescription
datastringString value representing scan result (username, code, email)
The CFS application will automatically process the scanned value and populate the appropriate input field or trigger the login/check-in flow.

scanCancelled

Indicates cancellation of a scan request. When received, the CFS typically:
  • Shows a toast notification to the user
  • Resets the scan state
  • May resend a cancellation acknowledgment to the external system
window.postMessage(
  {
    type: "scanCancelled",
    data: null
  },
  "*"
);

Event Data

No additional parameters required.

Event Flow Examples

Typical event sequence for customer check-in:
  1. CFS → POS: buttonClick (user clicks scan button)
  2. POS activates scanner
  3. POS → CFS: scanCompleted (with scanned email/phone)
  4. CFS processes check-in
Alternatively, if the user cancels:
  1. CFS → POS: buttonClick (user clicks scan button)
  2. POS activates scanner
  3. User cancels scan
  4. POS → CFS: scanCancelled
  5. CFS shows cancellation message
Typical event sequence for form interaction:
  1. CFS → POS: inputFocus (user focuses on input field)
  2. POS prepares for input (e.g., shows keyboard)
  3. User enters data and submits
  4. POS → CFS: formSubmitted
  5. CFS closes iframe/modal
Preventing inactivity timeouts:
  • POS → CFS: Send userActivity events periodically
  • CFS resets inactivity timer
  • Prevents “Are you still here?” prompts
Send userActivity events every 30-60 seconds during active customer interactions.

Implementation Guide

1

Set Up Event Listener

In your POS system, add a message event listener to receive events from the CFS:
window.addEventListener('message', (event) => {
  const message = event.data as IframeMessageData<any>;
  
  switch (message.type) {
    case 'init':
      console.log('CFS initialized:', message.data);
      break;
    case 'buttonClick':
      handleButtonClick(message.data);
      break;
    case 'inputFocus':
      handleInputFocus(message.data);
      break;
    // Handle other events...
  }
});
2

Send Events to CFS

Send events from your POS system to the CFS iframe:
const cfsIframe = document.getElementById('cfs-iframe') as HTMLIFrameElement;

cfsIframe.contentWindow?.postMessage(
  {
    type: 'scanCompleted',
    data: 'customer@example.com'
  },
  '*'
);
3

Handle Event Responses

Implement handlers for each event type based on your business logic:
function handleButtonClick(data: { targetId: string }) {
  if (data.targetId === 'scan') {
    // Activate hardware scanner
    activateScanner();
  }
}

Best Practices

Validate Event Origin

In production, validate the event origin instead of accepting all origins ("*").

Error Handling

Implement robust error handling for message parsing and event processing.

Type Safety

Use TypeScript interfaces to ensure type safety for event data.

Event Logging

Log all events during development to debug integration issues.

Next Steps