INTEGRATION / EVENTS
Player Events
The events p2lrn:* They describe the reproduction cycle with a stable contract. You can listen to them in the DOM to react in the interface or receive the same canonical stream using HostAdapter.emitEvent() for analytics and persistence.
1. Two ways to receive them
For a specific screen you can listen CustomEvent about the Player. For a centralized integration use emitEvent; This way you don't depend on mounting different listeners in each view.
const player = document.querySelector('p2lrn-player');
player.addEventListener('p2lrn:score', (event) => {
console.log(event.detail);
console.log(event.detail.event);
});In DOM, payload fields appear directly in event.detail, along with event.detail.context and the complete canonical envelope in event.detail.event.
2. Canonical envelope
The object you receive HostAdapter.emitEvent(event, context) It always maintains the same envelope, regardless of the renderer that originates it.
{
"schema": "https://p2lrn.org/schema/runtime-event/1",
"version": "1",
"type": "p2lrn:complete",
"timestamp": "2026-10-16T08:30:00.000Z",
"context": {
"packageId": "urn:uuid:...",
"contentRoot": "sha256:...",
"entityId": "urn:uuid:...",
"resourceId": "urn:uuid:...",
"representationId": "urn:uuid:...",
"rendererId": "https://p2lrn.org/renderer/..."
},
"payload": {}
}schema and version identify the contract; type identifies the event; timestamp it is runtime time; context locate the content; payload contains the specific data.
3. Loading and rendering events
p2lrn:readyThe package has been uploaded and verified enough to be ready. Includes packageId and contentRoot.
p2lrn:renderedAn entity has been rendered with a specific renderer. Progression can use it to mark viewed.
p2lrn:activityreadyThe internal runtime of an activity is now ready. It can include activity type, runtime, SCORM version, H5P library or isolation topology.
4. Interaction events
p2lrn:answerAnswer to a native question. Includes questionId and the normalized response.
p2lrn:progressInternal advancement of a compatible activity. In questionnaires it includes value, answered and total.
p2lrn:timeupdateUpdate the remaining time of an attempt or timed question.
p2lrn:timeoutA question or attempt has timed out.
p2lrn:navigationResult of a SCORM 2004 navigation request when the sequencer intervenes.
p2lrn:progress It does not mean overall progress of the course.Describes the progress that an activity publishes. Course progress is determined by the status and rules of Progress.
5. Status, score and completion
p2lrn:statechangeThe resumption status of an activity has changed. It may contain native responses, CMI SCORM or H5P status depending on the runtime.
p2lrn:scoreStructured scoring. Common fields are graded, raw, max, normalized and, when they exist, passed or completed.
p2lrn:completeThe activity has reported completion. The payload depends on the runtime and can include score, responses, status or terminal statement.
p2lrn:progressionchangeThe calculated progression status for an entity has changed: viewed, completed, approved, or grade percentage.
6. H5P and xAPI
H5P can issue xAPI statements. P2LRN exposes them without converting them into the platform's trusted identity.
p2lrn:xapiIncludes runtime:"h5p", he statement generated by content, source:"content-runtime" and authoritative:false.
p2lrn:scoreWhen statement.result contains score/success/completion, P2LRN derives a common form for the note.
p2lrn:completeIt is issued with terminal verbs completed, passed or failed.
If you are sending xAPI to an LRS, rebuild actor, authority, registration/intent, and other trust fields on your platform server.
7. Errors
p2lrn:error includes a phase when the implementation knows the phase that failed. It can appear when loading the package, rendering content, saving state, reporting note, sending events, resolving sequencing, or executing a runtime.
The technical error is used for diagnosis. Your application interface should decide what message is taught to the learner and what errors are recoverable.
8. Order and persistence with Host Adapter
The calls to emitEvent are serialized by Adapter: one event is delivered after the previous one. If your callback fails, P2LRN locally produces a p2lrn:error phase emitEvent without recursively forwarding that same error to the Adapter that is failing.
For an analytical history, keep the canonical envelope. To resume use saveState; do not try to reconstruct the current state by reproducing the entire event log unless your platform has expressly designed it that way.
9. What events to save
It is not mandatory to store all events. A platform can save only notes/status, or maintain a full log if you need detailed analytics.
saveState is more direct than storing each statechange.
reportScore avoids relying on interpreting all scoring events.
Preserves answer, progress, xapi or CMI SCORM depending on the content.
Keep the canonical envelope, add your attemptId and a receivedAt of the server.
10. Names you should use
p2lrn:* published.The runtime maintains internal support for historical names, but a new integration should listen to and persist only current P2LRN names.
The guide Metrics and analytics explains what to extract from quizzes, SCORM, H5P and progression and how to associate it with learner and attempt.
Intents and rich interactions
Native quizzes now emit explicit intent and interaction cycle events so that a platform can distinguish start, resume, and deliver without rebuilding them from the DOM.
p2lrn:attemptPhases started, resumed and submitted, with attempt number and progress counters. The attempt event does not duplicate the learner's raw responses.
p2lrn:interaction · answer-changeIndicates that you changed the answer to a question and includes questionId and questionType, but it doesn't copy the entire response into the analytic event.
p2lrn:interaction · collaborationVoting, whiteboard notes, contributions, and peer reviews all use the same canonical envelope of interaction.
p2lrn:interaction · resources/meansResource openings and media-relevant interactions can retain their semantic family without relying on the visible interface.
The learner's identity, enrollment, and actual attempt remain the property of the host. The event describes what happened in the content; the platform adds its private context by persisting it.