Cross-document messages
Interact with the virtual device via a Javascript post-message API
Cross-document messaging, when enabled via the &xdocMsg=true query parameter, allows you to issue commands to the embedded iFrame via Javascript via postMessage(message, targetOrigin).
Messages without any parameters can be passed directly as strings, e.g.
1
postMessage('requestSession', '*')
Copied!
Messages with parameters should be passed as objects with the message name in the type field. E.g.
1
postMessage({ type: 'mouseclick', x: 100, y:100 }, '*')
Copied!

Sendable Messages

requestSession

Equivalent to clicking play
1
postMessage('requestSession', '*')
Copied!

emitHomeButton

Taps the home button for iOS apps when available
1
postMessage('emitHomeButton', '*')
Copied!

rotateLeft

Rotates counter-clockwise
1
postMessage('rotateLeft', '*')
Copied!

rotateRight

Rotates clockwise
1
postMessage('rotateRight', '*')
Copied!

setScale

Sets device scale to a value between 10 and 100
1
postMessage({ type: 'setScale', value: 50 })
Copied!

saveScreenshot

Prompts user to download screenshot
1
postMessage('saveScreenshot', '*')
Copied!

getScreenshot

Sends screenshot data directly to parent window. See the screenshot event the iFrame posts to the parent.
1
postMessage('getScreenshot', '*')
Copied!

heartbeat

Sends heartbeat to prevent inactivity timeout
1
postMessage('heartbeat', '*')
Copied!

mouseclick

Sends click event at the provided coordinates
1
postMessage({ type: 'mouseclick', x: 100, y:100 }, '*')
Copied!

pasteText

Pastes the provided text
1
postMessage({ type: 'pasteText', value: 'Hello World' }, '*')
Copied!

keypress

Sends keypress. key should be a string that identifies the key pressed, e.g. 'a'. Acceptable values on Android also include 'volumeUp' and 'volumeDown'.
1
postMessage({ type: 'keypress', key: 'a', shiftKey: true }, '*') // would send 'A"
Copied!

language

Sets language, restarts app
1
postMessage({ type: 'language', value: 'fr' }, '*')
Copied!

location

Sets location. value should be 2-length array that contains [latitude, longitude]
1
postMessage({ type: 'location', value: [50.0, -100.0] }, '*')
Copied!

url

Opens deep-link or regular URL in Safari
1
postMessage({ type: 'url', value: 'https://appetize.io' }, '*')
Copied!

shakeDevice

Send shake gesture to iOS apps
1
postMessage('shakeDevice', '*')
Copied!

androidKeycodeMenu

Sends Android KEYCODE_MENU command
1
postMessage('androidKeycodeMenu', '*')
Copied!

biometryMatch

(Android 8+ only) simulate a matching fingerprint
1
postMessage('biometryMatch', '*')
Copied!

biometryNonMatch

(Android 8+ only) simulate a non-matching fingerprint
1
postMessage('biometryNonMatch', '*')
Copied!

disableInteractions

Disables all user interactions
1
postMessage('disableInteractions', '*')
Copied!

enableInteractions

Re-enables all user interactions
1
postMessage('enableInteractions', '*')
Copied!

restartApp

Kills and restarts app in same session
1
postMessage('restartApp', '*')
Copied!

endSession

Ends the session
1
postMessage('endSession', '*')
Copied!

Receivable Messages

The iFrame also posts messages to the parent window via message event. You can listen for them with an event handler on the window:
1
window.addEventListener('message', (event) => {
2
const type = typeof event.data === 'string' ? event.data : event.data.type
3
4
console.log(type)
5
})
Copied!

userInteractionReceived

Session has received an interaction from the user
1
{
2
data: {
3
type: "userInteractionReceived",
4
value: {
5
altKey: boolean,
6
shiftKey: boolean,
7
timeStamp: number,
8
type: string,
9
xPos: number,
10
yPost: number
11
}
12
}
13
}
Copied!

heartbeatReceived

Heartbeat event received
1
{
2
data: "heartbeatReceived"
3
}
Copied!

orientationChanged

Device orientation has changed
1
{
2
data: {
3
type: "orientationChanged",
4
value: "landscape" | "portrait"
5
}
6
}
Copied!

sessionRequested

Session has been requested
1
{
2
data: "sessionRequested"
3
}
Copied!

userError

An error occurred while starting session
1
{
2
data: {
3
type: "userError",
4
value: string // error message
5
}
6
}
Copied!

sessionQueued

You have entered a system-level queue (awaiting device availability)
1
{
2
data: "sessionQueued"
3
}
Copied!

sessionQueuedPosition

Position of session queue
1
{
2
data: {
3
type: "sessionQueuedPosition",
4
position: number
5
}
6
}
Copied!

accountQueued

You have entered an account-level queue (concurrent users)
1
{
2
data: "accountQueued"
3
}
Copied!

accountQueuedPosition

Account queue position
1
{
2
data: {
3
type: "accountQueuedPosition",
4
position: number
5
}
6
}
Copied!

appLaunch

App launch command sent
1
{
2
data: "appLaunch"
3
}
Copied!

firstFrameReceived

First frame received
1
{
2
data: "firstFrameReceived"
3
}
Copied!

timeoutWarning

Session is about to timeout in 10 seconds
1
{
2
data: "timeoutWarning"
3
}
Copied!

sessionEnded

Session has ended
1
{
2
data: "sessionEnded"
3
}
Copied!

screenshot

Screenshot data received
1
{
2
data: {
3
type: "screenshot",
4
data: string // base64 encoded image data
5
}
6
}
Copied!

sessionConnecting

Passes the identifying token for the session
1
{
2
data: {
3
type: "sessionConnecting",
4
token: string,
5
path: string
6
}
7
}
Copied!

chromeDevToolsUrl

URL to view dev tools for the device (only if network intercept enabled)
1
{
2
data: {
3
type: "chromeDevToolsUrl",
4
value: string
5
}
6
}
Copied!

interceptResponse

Intercepted network response.
This is only emitted if network intercept enabled (proxy=intercept query param)
1
{
2
data: {
3
type: "interceptResponse",
4
value: {
5
cache: object
6
request: {
7
bodySize: number
8
cookies: Array<{ name: string, value: string }>
9
headers: Array<{ name: string, value: string }>
10
headersSize: number
11
httpVersion: string
12
method: string
13
queryString: Array<{ name: string, value: string }>
14
url: string
15
}
16
requestId: string
17
serverIPAddress: string
18
}
19
}
20
}
Copied!

interceptRequest

Intercepted network request.
This is only emitted if network intercept enabled (proxy=intercept query param)
1
{
2
data: {
3
type: "interceptRequest",
4
value: {
5
cache: object
6
request: {
7
bodySize: number
8
cookies: Array<{ name: string, value: string }>
9
headers: Array<{ name: string, value: string }>
10
headersSize: number
11
httpVersion: string
12
method: string
13
queryString: Array<{ name: string, value: string }>
14
url: string
15
}
16
requestId: string
17
serverIPAddress: string
18
}
19
}
20
}
Copied!

debug

Logged messages from the device.
This is only emitted if debug log is enabled (debug=true query param)
1
{
2
data: {
3
type: "debug",
4
value: string
5
}
6
}
Copied!

deviceDimensions

The dimensions of the current device. If the screenOnly query param is true, the dimensions will be for the screen.
1
{
2
data: {
3
type: "deviceDimensions",
4
value: {
5
width: number,
6
height: number
7
}
8
}
9
}
Copied!