← Developer docs

Embed protocol

Every postMessage exchanged between the iframe and the parent is JSON of the form { source, v, type, data }.

Iframe → parent (events)

Each event has source: "mtga" and v: 1. A listener should check both event.source === iframe.contentWindow and event.origin, as <mtga-embed> does, so another frame on the page cannot pose as the embed.

typedata
ready{}
lesson.completed{ lessonId, moduleId, programId }
module.completed{ moduleId, programId, score? }
program.completed{ programId, completedAt, issuanceIds[] }
assessment.passed{ assessmentId, score, attemptNumber }
assessment.failed{ assessmentId, score, attemptNumber, attemptsRemaining }
navigation{ path }
height{ px }
error{ code, message }

Parent → iframe (commands)

Each command has source: "mtga-host" and v: 1. Send via iframe.contentWindow.postMessage(...) from the page that holds the iframe; commands from any other frame are ignored. The <mtga-embed> element's postCommand(...) does this for you. Always pass the embed's origin as the target, never "*": refresh-token carries a token, and"*" would hand it to any page the frame navigated to.

typedata
navigate{ path }
refresh-token{ token }
set-locale{ locale: 'en' | 'es' }