Remote Control

This is a more advanced use of Arcade and may require a developer on your team.

Arcades are self-contained demo “widgets” that operate on their own when they’re embedded. Users can navigate the Arcade by interacting with hotspots. But what if you wanted to have an alternative way for your users to navigate the Arcade instead of clicking hotspots?

Here’s an example of how you might provide an alternative way for your users to navigate an Arcade:

In the above example, a sidebar nav sits beside the demo allowing the user to navigate outside of the Arcade. This also allows users to jump across steps and are no longer forced to follow the Arcade creator’s prescribed order for navigating through the demo.

The difficult part about implementing a navigation UI for Arcades is going to be the UI itself. Each customer will want something different. So, we at Arcade have taken a different approach. We call it Remote Control.

What is Remote Control?

Remote Control allows your users to control the Arcade from your website. With Remote Control, your users aren’t required to interact with hotspots in order to navigate your Arcade. You can use Remote Control to generate your own custom navigation UI for your Arcades.

How does Remote Control work?

In order to allow your website to generate a nav UI that can be styled to your liking, we have chosen not to build the nav UI within the Arcade. Instead, our approach is to send the host — your website — details about the Arcade so that your website can construct the nav on its own.

A simple approach to enable this is to use the [window.postMessage() API which is supported by all major browsers.

The window.postMessage() method safely enables cross-origin communication between [Window](<https://developer.mozilla.org/en-US/docs/Web/API/Window>) objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.

Essentially, window.postMessage() allows us to communicate between the Arcade and its host. Here’s a sequence diagram of the interaction between three actors: the user, the host, and the Arcade.

With this strategy, there are essentially two interactions:

  1. Arcade to Host: sends Arcade metadata at initialization of Arcade and during navigation events in the Arcade (i.e., movement between steps)

  2. Host to Arcade: when a user clicks on a nav item in the custom nav, the host can send a message instructing the Arcade to navigate to a particular step in that Arcade.

Arcade to Host

When the Arcade initializes, it will send the following postMessage to the host:

window.parent.postMessage(
  {
    event: 'state-update',
    arcade: {
      id: '123',
        name: 'My Awesome Arcade',
        description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        steps: [
          {
            id: '456',
            name: '<for future use>',
            description: '<for future use>',
            order: 1,
            isActive: true
          },
          {
            id: '789',
            name: '<for future use>',
            description: '<for future use>',
            order: 2,
            isActive: false
          },
          ...
        ],
      },
    },
  '*'
)

The postMessage contains basic metadata about the Arcade including its steps. This metadata can be used to generate custom navigation to the Arcade inside the host’s website.

If the Arcade’s state changes (e.g., the user clicks on a hotspot to navigate steps), an updated postMessage will be sent consisting of a similar payload as what’s above. The only difference will be that the isActive property on the steps will change to reflect the new active step.

The host website will need to establish a listener for the postMessage the Arcade sends. Here’s an example listener:

// Add postMessage listener on the Host

function processIncomingMsg (evt) {
  // Check to make sure that the event is from Arcade and is generated by a user
  if (evt.origin !== 'https://demo.arcade.software' || !evt.isTrusted) return;

  if (evt.data.event === 'arcade-state-update') {
		//Do something... like set the state in your app/component etc
    setArcade(evt.data.arcade);
  }
};
window.addEventListener('message', processIncomingMsg);

If you’re using React, this can be placed inside a useEffect so that the component can re-render when changes are received from Arcade.

// Set up postMessage listener on the Host

const [arcade, setArcade] = useState({});

useEffect(() => {
  const processIncomingMsg = (evt) => {
  // Check to make sure that the event is from Arcade and is generated by a user
  if (evt.origin !== 'https://demo.arcade.software' || !evt.isTrusted) return;

    if (evt.data.event === 'arcade-state-update') {
      setArcade(evt.data.arcade);
    }
  };
  window.addEventListener('message', processIncomingMsg);
  return () => window.removeEventListener('message', processIncomingMsg);
}, []);

It’s important to validate the evt.origin to make sure that the message is coming from Arcade and also make sure that the event is user generated and not from a script (evt.isTrusted). In the future, Arcade may send other events to the host, so make sure you’re listening for evt.data.event === 'state-update'.

Host to Arcade

When you want to interact with your custom UI element to control the Arcade, you’ll need to send a postMessage to the Arcade you’d like to control. For example, if you’d like to navigate to a step within the Arcade, you can send the following message:

// Navigate to a step in the Arcade from the Host
const iframe = document.querySelector(`iframe[src*=${arcadeId}]`);
iframe?.contentWindow?.postMessage(
  {
    event: 'navigate-to-step',
    stepId, // The step to navigate to
  },
  '*'
);

Notice you’ll need to direct your postMessage directly to the iframe element you’d like to receive the postMessage. The example above will instruct the Arcade to navigate to a particular step based on the stepId inside the payload. The Arcade will react and navigate to the selected step when this message is sent. It will also send a postMessage back to the host with a state-update event.

Another way to use the Remote Control feature is for restarting the Arcade from the host page. This will reset the Arcade back to its first step.

// Reset an Arcade to the first step
const iframe = document.querySelector(`iframe[src*=${arcadeId}]`);
iframe?.contentWindow?.postMessage({ event: 'reset'}, '*');

Example

Here’s an example of all of this working:

Availability

Remote Control is a feature of Arcade Growth. If you’re a Growth customer, make sure your Arcade belongs to the team folder. Arcades inside a personal space won’t work with Remote Control.

If you’re not a Growth customer, you can upgrade your account to take advantage of other Growth features.

Last updated