GoRunner docs
Search or askSearch⌘K

SDK

The script that puts GoRunner in your page: GoRunnerEmbed.mount(), its options, methods, events and errors.

SDK 1.4.0 · Embed · Self-hosted with an Embed license

Load it

Your installation serves the SDK. /embed.js is always the newest; it sets window.GoRunnerEmbed.

To pin a version, load it by number. SDK 1.3.0 is still served, byte for byte, for pages that check it with Subresource Integrity.

The SDK also has an npm package, @gorunner/embed, with a React component in @gorunner/embed/react. Neither is published yet. With the package, url is required.

The React component, not published yet

<GoRunnerEmbed url={…} getCode={getCode} accountKey={account.id} style={{ height: 640 }} />

It takes every mount() option except container, plus className, style, accountKey, embedRef, onReady(instance) and onError(error).

It mounts once. A changed theme calls setTheme, appearance (compared by value) setAppearance, new turnOff ids turnOff, and accountKey switchAccount. Removing a turnOff id needs a new key. url and page are read at mount only. Under StrictMode it still makes one frame, and on a server it renders an empty element.

html
<script
  src="https://automations.example.com/embed.js"
></script>

Pinned to 1.4.0

html
<script
  src="https://automations.example.com/embed-sdk/1.4.0/embed.js"
></script>

mount()

mount(options) opens the embed in your element and resolves when it is ready, with the embed itself. It rejects with an EmbedError when it can’t open.

getCode runs when the embed opens and whenever it needs a new session. Its reason is one of mount, renew, expired, reload, switch.

The embed’s state is mounting, ready, reconnecting, ended, unmounted. It also has id, route, account and unsaved. GoRunnerEmbed.protocol is the protocol it speaks, "gorunner-embed/1", and GoRunnerEmbed.version is the SDK’s version, such as "1.4.0".

js
const embed = await GoRunnerEmbed.mount({
  container: "#automations",
  getCode: async ({ reason }) => {
    const url = "/api/gorunner/login-code"
    const res = await fetch(url, { method: "POST" })
    return (await res.json()).code
  },
  page: "workflows",
  theme: "system",
  turnOff: ["templates"],
  onEvent: (event) => console.log(event.type),
})

Options

containerRequired

The element, or a selector for it. It needs a height: the embed fills it. Under 200 px tall, the frame gets a minimum of 640 px, and the console says so.

getCodeRequired

Returns a login code from your server, 1 to 512 characters. During a renewal the frame waits 15 seconds for it, and tries a few times before session_failed. See Login codes and sessions.

urlOptional

The installation’s address, such as https://automations.example.com, with no path. A path, query or credentials are refused with invalid_options. /embed.js fills it in with its own. The npm package needs it.

pageOptional

Where it opens: overview, workflows, runs, connections, templates, assistant, tokens, or { workflow }, { workflow, run }, { run }, { connection }, { template }, { path }, or { newWorkflow: true } with an optional name. Default: the first page the person may see.

themeOptional

light, dark, system: system, the default, follows your page’s color scheme. Ignored while Branding sets Light or dark to Light or Dark.

turnOffOptional

Switches to turn off for this page, at most 64. It can only turn things off. See Switches.

appearanceOptional

A look for this page, over the installation’s own. See A look for one embed.

onEventOptional

Called with every event.

onBackOptional

Given, your page owns Back: the embed tells you instead of going back itself.

buildLinkOptional

Given, Copy link copies your page’s own address for a route. It must return an http or https address. Without it, there is no link to copy.

titleOptional

The frame’s accessible name, up to 200 characters. Default: the installation’s product name.

timeoutMsOptional

How long the embed may take to answer, in milliseconds: 5000 to 600000. Default 20000.

Methods

Each returns a promise. One that needs the frame rejects with not_ready until the embed is ready, and gives up after 10 seconds without an answer.

navigate(page)
Opens a page, with the same values as page. Resolves with the route reached.
connect({ piece })
Opens the connection sheet for one app. Resolves with { connection }: the connection made, or null when none was.
setTheme(theme)
Changes the theme, unless Branding fixes it.
setAppearance(look)
Changes the look. null goes back to the installation’s. Resolves with { flags }, what it corrected or couldn’t apply. Rejects with invalid_appearance for a look it refuses.
turnOff(keys)
Turns more switches off.
switchAccount({ page? })
Ends this session and asks getCode for a new code, with the reason switch: for the account your server now names. It loads a fresh document, so nothing of the old account stays, and opens page, else the mount’s named page, else the first allowed. Rejects with busy while signing in.
on(type, listener)
Listens to one event, or "*" for all. Returns a function that stops it. A type no event has is accepted, with a console warning and a non-fatal invalid_options error event.
unmount()
Ends the session and removes the frame, after waiting up to 3 seconds for it to save. Safe to call twice.
js
const workflowId = "your-workflow-id" // from workflow.created
await embed.navigate({ workflow: workflowId })
await embed.navigate({
  newWorkflow: true,
  name: "Order intake",
})

const { connection } = await embed.connect({
  piece: "gmail",
})

await embed.setTheme("dark")
await embed.turnOff(["delete", "importExport"])
await embed.switchAccount({ page: "overview" })
await embed.unmount()

A look for one embed

The appearance option at mount, or setAppearance() later, lays a look over the installation’s Branding for this embed. Yours goes on top, leaf by leaf. Bars and menus stay solid.

preset
paper, soft, crisp.
colors
Ten roles, brand, onBrand, page, surface, raised, border, text, textMuted, link, focus, each { light, dark } as #rrggbb. page: "transparent" lets your page show through, in the embed only; behind is the color assumed under it.
corners
control, card, dialog: 0 to 20.
depth
shadow: print, none, subtle, raised. frame: 1 or 0.
type
body, heading, baseSize (13 to 16), headingWeight (500, 560, 600 or 700), labelCase (upper or normal). A font must be a WOFF2 or WOFF file on your page’s own website.
density
comfortable, compact.
canvas.background
dots, grid, plain.
fit
outerPadding (0, 8, 12, 16, 24 or 32), pageHeader.
embedTheme
host (Follow the page), light or dark.

A look is at most 16 KB as JSON. A font service’s stylesheet is refused (invalid_appearance, font_stylesheet): a font is one font file. Up to 8 KB rides in the frame’s address fragment, which never reaches a server, so even the first paint wears it. What the frame changed comes back as flags.

GoRunnerEmbed.matchHost() proposes a look from your page’s own styles: its background, text, font, a button and a card. It never applies anything. Its options are root, button, card and allowedOrigins. It answers appearance, the theme it read, the flags the frame will raise, and notes on what it couldn’t read: no_background, gradient_background, font_not_loadable, font_cross_origin, button_not_found, button_transparent, card_not_found, radius_clamped, shadow_unrecognised.

js
const embed = await GoRunnerEmbed.mount({
  container: "#automations",
  getCode,
  appearance: {
    preset: "soft",
    colors: { brand: { light: "#0f6e5a", dark: "#5cc8a8" } },
    corners: { control: 8, card: 12 },
    density: "compact",
    fit: { outerPadding: 0, pageHeader: false },
  },
})

const { flags } = await embed.setAppearance({
  colors: {
    page: { light: "transparent", behind: { light: "#f7f7f5" } },
  },
})

A look proposed from your page

js
const proposal = GoRunnerEmbed.matchHost({ root: "#automations" })
const embed = await GoRunnerEmbed.mount({
  container: "#automations",
  getCode,
  appearance: proposal.appearance,
})

Events

The embed
ready, error, session.renewed
Where it is
route.changed, title.changed, back, unsaved.changed
Workflows
workflow.created, workflow.saved, workflow.published, workflow.unpublished, workflow.deleted
Runs
run.started, run.finished, run.failed
Connections
connection.created, connection.removed

Each event’s fields are in Events and the protocol.

js
const stop = embed.on("run.finished", (event) => {
  console.log(event.workflow, event.run.status)
})

embed.on("*", (event) => analytics.track(event.type))

stop() // stop listening

Errors

Everything that fails rejects with an EmbedError, with code, message and sometimes details. After mounting, problems arrive as the error event, such as account_suspended.

For what to do about each, see Troubleshooting. For every code, see Error codes › SDK.

js
try {
  await GoRunnerEmbed.mount({ container, getCode })
} catch (error) {
  // an EmbedError
  if (error.code === "not_allowed_here") {
    // add this website under Platform › Partner keys
  }
  console.error(error.code, error.message)
}