Player Events

Using postMessage events from the KissKH player for progress tracking, auto-next, and watch history

Updated May 5, 2026
OtakuThemes Team

Overview

The KissKH player sends postMessage events to the parent window during playback. You can listen for these events on your page to build features like auto-next episode, watch progress tracking, and watch history.

KissKH Player DocsKissKH Player Docs


Event Structure

Events are sent as JSON objects. There are two formats:

KissKH Channel Events

{
  "channel": "kisskh",
  "event": "time",
  "currentTime": 42.5,
  "duration": 1440.0
}
FieldDescription
channelAlways "kisskh"
eventEvent name — see table below
currentTimeCurrent playback position in seconds
durationTotal episode duration in seconds

Watching Log Events

{
  "type": "watching-log",
  "currentTime": 42.5,
  "duration": 1440.0
}

Event Reference

EventFormatWhen fired
time{ channel: "kisskh", event: "time", currentTime, duration }Continuously during playback (every few seconds)
complete{ channel: "kisskh", event: "complete" }When the episode finishes playing
error{ channel: "kisskh", event: "error", message }When playback fails or a stream error occurs
watching-log{ type: "watching-log", currentTime, duration }Periodic watch-time log during playback

Listening for Events

Add a message event listener on window in your parent page:

window.addEventListener("message", function (event) {
  let data = event.data;
 
  // Some browsers may send the data as a JSON string
  if (typeof data === "string") {
    try { data = JSON.parse(data); } catch (e) { return; }
  }
 
  // KissKH channel events
  if (data.channel === "kisskh") {
    if (data.event === "complete") {
      // Episode finished — load the next episode
      loadNextEpisode();
    }
 
    if (data.event === "time") {
      // Save watch progress
      saveProgress(data.currentTime, data.duration);
    }
 
    if (data.event === "error") {
      // Handle playback error
      console.error("Player error:", data.message);
    }
  }
 
  // Watching log (alternative progress format)
  if (data.type === "watching-log") {
    saveProgress(data.currentTime, data.duration);
  }
});

Auto-Next Episode Example

window.addEventListener("message", function (event) {
  let data = event.data;
  if (typeof data === "string") {
    try { data = JSON.parse(data); } catch (e) { return; }
  }
 
  if (data.channel === "kisskh" && data.event === "complete") {
    const iframe = document.getElementById("player-iframe");
    if (iframe && nextEpisodeId) {
      iframe.src = "https://your-server.com/kisskh/" + nextEpisodeId;
    }
  }
});

Watch Progress Example

let lastSaved = 0;
 
window.addEventListener("message", function (event) {
  let data = event.data;
  if (typeof data === "string") {
    try { data = JSON.parse(data); } catch (e) { return; }
  }
 
  if (data.channel === "kisskh" && data.event === "time") {
    // Save every 10 seconds to avoid excessive writes
    if (data.currentTime - lastSaved > 10) {
      lastSaved = data.currentTime;
      localStorage.setItem("progress-" + episodeId, data.currentTime);
    }
  }
});

Security Note

Always validate event.origin in production if your server is restricted to specific domains:

window.addEventListener("message", function (event) {
  if (event.origin !== "https://your-server.com") return;
  // ... handle event
});