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.
| type | data |
|---|---|
| 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.
| type | data |
|---|---|
| navigate | { path } |
| refresh-token | { token } |
| set-locale | { locale: 'en' | 'es' } |