SPLICE iframe Protocol: Specification
If you read this as the implementer of a learning system that embeds smart learning content as iframes, you only need to care about the message protocol. You may find this starter code helpful.
If you read this as the implementer of smart learning content, which you would like to make available to learning systems, you may want to make use of this reference implementation that provides a friendly JavaScript interface for the message protocol.
Messages
These messages are supported:
The reportScoreAndState Message
The smart learning content sends this message whenever the activity’s state and/or score changes.
{ subject: 'SPLICE.reportScoreAndState', message_id: a unique string ID for this message, score: a floating-point number between 0 and 1 state: an arbitrary JavaScript object }
The learning system should update the user’s score and optionally store the state.
The getState Message
{ subject: 'SPLICE.getState', message_id: a unique string ID for this message, domain_id: an optional globally unique domain chosen by the content provider, content_id: an optional unique ID in the domain, }
If the domain_id
is not specified, it is implied to be the host domain that serves the iframe of this activity. If the content_id
is not specified, it is implied to be the part of the iframe URL after the scheme, host, and port.
Use these IDs if you want to provide an identifier for the smart learning content that is more canonical than the iframe URL.
The getState
message has a response:
{ subject: "SPLICE.getState.response", message_id: the same ID as the request, state: the previously reported state, user_id: an optional unique and opaque user ID, user_model: an optional JSON object describing information about the user in a format that is specific to the embedding system or that may be standardized in the future context_id: an optional unique and opaque ID of the context (such as a s course assignment or ebook section) }
If you do not support state restoration, reply to the getState
message with a state of null
.
The response may contain more information about the user that the smart learning content can interpret, such as their prior skill level. This information is not currently standardized.
If there is an error in the request, the response must contain, with key error
, a JavaScript object
{ code: a text string with an error code message: optionally, a text string with a humanly readable message }
NOTE: We don’t use the lti.get_data, lti.put_data message from LTI for state storage because those data are described to be “short lived”
The sendEvent Message
This message informs about interactions with the smart learning content that are unrelated to scoring and state restoration. The learning system may choose to log or store them, and to make them available to interested parties, such as education researchers. The message content is not currently standardized.
{ subject: 'SPLICE.sendEvent', message_id: a unique string ID for this message, name: ..., data: ..., error: an optional error that may be of interest to the embedding page }
An error contains, with key error
, a JavaScript object
{ code: a text string with an error code message: optionally, a text string with a humanly readable message }
The lti.frameResize Message
The embedded iframe sends this message whenever its size changes. This allows the embedding page to display the iframe without scroll bars.
{ subject: lti.frameResize', message_id: a unique string ID for this message, height: ..., width: ... }
Protocol Implementation Notes
If you implement a smart learning system that embeds iframes with smart learning content, you need to be aware of a couple of issues with iframe communication.
When receiving a message from an iframe, and if you have more than one, you want to know which iframe sent it. Unfortunately, you cannot do the obvious and consult event.source.location.href
. That’s a CORS violation. Instead, use code similar to the following:
function sendingIframe(event) { for (const f of document.getElementsByTagName('iframe')) if (f.contentWindow === event.source) return f return undefined } window.addEventListener("message", event => { let iframe = sendingIframe(event) let url = iframe.src . . . })
When sending a message to an iframe, use
event.source.postMessage({ message_id: event.data.message_id, subject: "SPLICE.getState.response", state: state, }, "*");
with a "*" for the targetOrigin parameter. Otherwise your message may not be delivered:
Listen to the lti.frameResize messages and adjust the size of the iframe, using code such as the following:
Let newHeight = event.data.height if ('chrome' in window) { const CHROME_FUDGE = 32 // to prevent scroll bars in Chrome newHeight += CHROME_FUDGE } if (iframe.scrollHeight < newHeight) iframe.style.height = newHeight + 'px'
JavaScript Reference Implementation
This section is addressed to authors of smart learning content, served as an HTML page, ready for inclusion as an iframe.
A reference implementation provides a simple JavaScript API that is easier to use than sending and receiving messages. You can use the JavaScript code as is, modify it for your situation, or provide your own messaging code.
The implementation supports multiple interactive elements on the page. Each of them has a location ID, which must be unique to the page. If you only have one element, simply provide an empty string as the ID.
The following calls are provided:
SPLICE.reportScoreAndState(location, score, state) SPLICE.getState(location, callback) SPLICE.sendEvent(location, name, data) SPLICE.configure(params)
- location: an ID string for the activity that is unique to this page.
- score: a floating-point number between 0 and 1
- state: an arbitrary JavaScript object
- callback: a function that is called with parameters location and state
- name: the event name
- data: an arbitrary JavaScript object
- params: a JavaScript object that is described below
Call SPLICE.reportScoreAndState
whenever an activity’s score changes.
If restoration of student work from a prior launch is desired, provide state information in each call to SPLICE.reportScoreAndState
.
Call the SPLICE.getScores
method when loading the page to retrieve the state information. Not all learning systems have the ability to save and restore state, so be prepared that this call may yield no information, or it may not even return. Call this method even if you are not interested in getting scores, to notify the learning system that your element is ready.
Optionally call SPLICE.configure
before making any other calls. You can specify the following parameters:
domain_id
: an optional globally unique domain chosen by the content providercontent_id
: an optional unique ID in the domain,weights
: a map from locations to weights, for combining the scores of each location
The reference implementation emits lti.frameResize
messages when the document size changes.
NOTE: We may want to standardize this API at some point in the future. Then we might want to replace the SPLICE
identifier with something like org.cssplice.content
.