Siirry sisältöön
Kehittäjän integraatiot

Yhdistä Puzzel omaan alustaasi

Puzzel voi antaa pelaajan tuloksen suoraan toiselle järjestelmälle — pistemäärän, etenemisen, vastatut kysymykset — ilman että kyseisen järjestelmän tarvitsee olla täysi LMS. Tämä sivu käy läpi jokaisen kanavan: mitä lähtee ulos, milloin se lähtee, ja pienimmän asian, joka sinun täytyy rakentaa sen vastaanottamiseksi.

Tulokset lähtevät
Webhookin kautta, tai viestinä aktiviteettia ympäröivälle sivulle
Sivusi voi
Kirjata pelaajan sisään ja nollata aktiviteetin
Otetaan käyttöön
Aktiviteettikohtaisesti, editorin Kehittäjä-valikossa
Sisältyy
Maksulliseen pakettiin — nämä asetukset ovat pois päältä ilmaisella tilillä

Minkä kanavan tarvitset?

Kolme asiaa voi lähteä aktiviteetista ulos ja yksi voi tulla sisään. Kumpi sopii, riippuu yhdestä kysymyksestä: istuuko pelaaja sinun sivullasi vai jossain aivan muualla?

Puzzelista ulos
Puzzeliin sisään

Tulosten webhook

Kytke editorissa päälle "Lähetä tulokset webhookiin" ja anna sille URL-osoite. Siitä lähtien pelaajan selain lähettää koko tuloksen POST-pyynnöllä kyseiseen osoitteeseen JSON-muodossa aina, kun pelaajan eteneminen tallennetaan.

Käyttöönotto
  1. 1 Avaa aktiviteetti editorissa ja siirry Kehittäjä-valikkoon.
  2. 2 Kytke päälle "Lähetä tulokset webhookiin" ja liitä päätepisteesi sen alla olevaan kenttään. Sen täytyy olla täydellinen URL-osoite — pelkkä verkkotunnus hylätään — ja sen täytyy olla https, koska selain estää tavallisen http-kutsun sivulta, joka on tarjottu https:n kautta.
  3. 3 Pelaa aktiviteettia itse kerran. Ensimmäinen POST-pyyntö saapuu heti, kun vastaat johonkin.
Vastaanottaja alusta loppuun
import express from 'express';

const app = express();

// The POST is made by the player's browser, so the browser asks permission
// first. Answer the preflight and the real request can land.
app.use((req, res, next) => {
  res.set('Access-Control-Allow-Origin', 'https://puzzel.org');
  res.set('Access-Control-Allow-Headers', 'Content-Type');
  if (req.method === 'OPTIONS') return res.sendStatus(204);
  next();
});

app.post('/puzzel/results', express.json(), async (req, res) => {
  const result = req.body;

  // One run posts several times as it goes. Key on the pair, not on an
  // insert: each call carries the whole state, so the newest simply wins.
  await db.results.upsert(
    { playerUid: result.playerUid, activityKey: result.activityKey },
    result
  );

  // Only act on the finish once.
  if (result.progress >= 100 || result.hasAlternateCompletion) {
    await markCourseStepComplete(result);
  }

  res.sendStatus(200);
});
Se laukeaa pelin aikana, ei vasta lopussa

Tulos lähtee ulos aina, kun merkintä tallennetaan: kirjoittamisen tauon jälkeen, kun kortti asetetaan paikalleen, kun kello pysähtyy, ja vielä kerran, kun aktiviteetti on valmis. Pitkässä sanaristikossa kutsuja kertyy pari kymmentä, ei yhtä — kirjoita siis käsittelijäsi upsertiksi, jonka avaimena on playerUid ja activityKey, älä lisäykseksi. Jokainen kutsu kantaa mukanaan koko tilan, joten uusin korvaa aina edellisen, ja kadonneen kutsun korjaa seuraava.

Miten erottaa valmistuminen tallennuksesta

progress on prosenttiluku: 100 tarkoittaa, että aktiviteetti on valmis. Muutama tyyppi voi päättyä saavuttamatta sitä — kokonaan vastattu Quiz, ratkaistu ratkaisukenttä — ja niissä on sen sijaan hasAlternateCompletion. Kohtele kumpaakin valmiina.

Sen lähettää pelaajan selain

POST-pyyntö tulee välilehdeltä, jolla aktiviteettia pelataan, ei Puzzelin palvelimelta. Useimmat webhookeja vastaanottamaan rakennetut päätepisteet hyväksyvät sen jo valmiiksi. Jos omasi ei koskaan näe pyyntöä, tämä on syy: selain kysyy luvan ensin, joten vastaa OPTIONS-esitarkistukseen Access-Control-Allow-Origin-otsakkeella, niin varsinainen POST seuraa perässä.

Kohtele hyötykuormaa väitteenä, ei todisteena

Pyynnössä ei ole allekirjoitusta, ja se tulee selaimesta, jota et hallitse, joten kuka tahansa sivua katsova voi lähettää sinulle samanlaisen. Se riittää edistymispalkkiin tai hallintapaneeliin. Kaikkea, mitä et antaisi oppilaan itse asettaa — laskettavaa arvosanaa, todistusta, maksua — varten tarkista se omasta Puzzel-hallintapaneelistasi löytyviä tuloksia vasten, tai anna pistemäärän kulkea sen sijaan LMS-arvosanaliitäntöjen kautta.

Tulokset sen ympäröivälle sivulle

Jos upotat aktiviteetin, voit lähettää saman JSON:n omalle sivullesi palvelimen sijaan. Kytke päälle "Lähetä tulokset upottavalle sivulle" ja kuuntele viestiä. Mikään ei poistu selaimesta, joten päätepistettä ei tarvitse rakentaa eikä CORSia tarvitse miettiä.

index.html
<iframe
  src="https://puzzel.org/en/quiz/embed?p=-Nq8sample_activity_key"
  width="100%"
  height="700"
  frameborder="0"
  allowfullscreen
></iframe>

<script>
  window.addEventListener('message', (event) => {
    if (event.origin !== 'https://puzzel.org') return;

    const result = event.data;
    if (!result || !result.activityKey) return;

    // Same shape the webhook posts, same advice: it arrives repeatedly.
    saveProgress(result);
  });
</script>
Tarkista, mistä viesti tuli

Kuuntelijasi kuulee jokaisen sivulle lähetetyn viestin, myös muilta kehyksiltä ja selainlaajennuksilta. Vertaa event.origin-arvoa osoitteeseen https://puzzel.org ennen kuin luotat sen sisältöön.

Sama hyötykuorma, sama ajoitus

Tämä on webhookin kaksoisolento: samat kentät, lähetettynä samoina hetkinä. Kaikki kohdassa "Mitä tulos sisältää" pätee myös tähän.

Valmistumissignaali

Pienin kanava, kun itse tulos ei kuulu sinulle: kytke päälle "Lähetä valmistumissignaali", ja sivusi saa yhden viestin heti, kun pelaaja lopettaa.

index.html
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://puzzel.org') return;
  if (event.data?.completed !== true) return;

  // { completed: true, activityKey: '-Nq8sample_activity_key' }
  unlockNextLesson(event.data.activityKey);
});
Mitä saapuu
{
  "completed": true,
  "activityKey": "-Nq8sample_activity_key"
}
Tulos on jo tallennettu, kun signaali saapuu

Signaali lähetetään tarkoituksella vasta, kun valmistumiseen johtanut tallennus on tehty, joten sivu, joka reagoi lukemalla tuloksen takaisin, löytää sen jo sieltä.

Vain iframen sisällä

Molemmat viestikanavat lähettävät viestin sivulle, joka kehystää aktiviteetin. Omalla välilehdellä avattuna kellekään ei ole ketä kertoa, joten mitään ei lähetetä.

Mitä tulos sisältää

Yksi muoto, kanavasta riippumatta. Pelaajan vastausten avaimina toimivat aktiviteetin omat kohdetunnisteet, joten samat avaimet löytyvät myös kohteesta correctUids.

KenttäTyyppiMitä se tekee
activityKey
aina
string
stringAktiviteetti, johon tulos kuuluu. Sama avain, jonka näet aktiviteetin omassa URL-osoitteessa, kohdan ?p= jälkeen.
playerUid
aina
string
stringKuka pelasi, anonyyminä tunnisteena. Pysyy samana tälle pelaajalle tällä laitteella, joten juuri sen mukaan tulokset kannattaa ryhmitellä — se ei ole sähköpostiosoite eikä Puzzel-tili.
player
joskus
object
objectRekisteröitymiskentät, joita aktiviteetti kysyy, sellaisina kuin määritit ne: nimi, sähköposti, luokka, student_id ja niin edelleen. Puuttuu, kunnes pelaaja on rekisteröitynyt, ja puuttuu kokonaan aktiviteetista, joka ei kysy mitään.
progress
aina
number
numberKuinka pitkälle on edetty, prosentteina. 100 tarkoittaa valmista.
timePassed
aina
number
numberAktiviteetissa käytetty aika, millisekunteina.
lastPlayedAt
aina
number
numberMilloin tämä tulos tallennettiin, Unix-aikaleimana millisekunteina.
createdAt
joskus
number
numberMilloin yritys aloitettiin, Unix-aikaleimana millisekunteina.
playerInput
joskus
object
objectMitä pelaaja todella syötti, ryhmiteltynä sen kohteen tunnisteen mukaan, johon syöte kuuluu. Sisällön muoto riippuu aktiviteettityypistä — sana, sijoitettujen korttien luettelo, valittu vaihtoehto.
correctUids
joskus
object
objectMitkä näistä kohteista ovat oikein, ryhmiteltynä samalla tavalla. Puuttuu, kun mihinkään ei ole vielä vastattu.
score
joskus
number
numberSaadut pisteet, tyypeillä, jotka pisteyttävät pelikerran. Puuttuu kaikkialla muualla — myös pelikerrasta, joka aidosti sai nolla pistettä, joten tarkista avaimen olemassaolo ennen kuin luet sen.
performance
joskus
number
numberTyypin oma mittari sille, kuinka hyvin meni, jos sellainen on käytössä — esimerkiksi sanaa minuutissa näppäilyharjoituksessa.
attempts
joskus
number
numberMonesko yritys tämä on: 1 ensimmäisellä kerralla, yksi lisää joka uudella aloituksella. Vain tyypeillä, jotka päättävät pelikerran kesken ja laskevat uusintayritykset.
knockedOut
joskus
boolean
booleanPelikerta päättyi väärään vastaukseen ja on ohi tulematta valmiiksi.
hasAlternateCompletion
joskus
boolean
booleanAktiviteetti saatiin valmiiksi tavalla, joka ei yllä 100 %:iin — kokonaan vastattu Quiz, ratkaistu ratkaisukenttä. Kohtele sitä valmistumisena.
missedKeys
joskus
array
arrayMerkit, joissa pelaaja jatkuvasti erehtyi, eniten erehdytty ensin. Vain näppäilyharjoituksessa.
contentVersion
joskus
number
numberMitä versiota aktiviteetin sisällöstä vastaan tätä pelattiin. Se muuttuu, kun omistaja muokkaa kysymyksiä, joten vanha tulos erottuu tuoreesta.
Valmis Quiz, sellaisena kuin se saapuu
{
  "activityKey": "-Nq8sample_activity_key",
  "playerUid": "kK3r9TzSampleAnonymousUid",
  "player": {
    "name": "Ava Ortega",
    "email": "ava@school.example",
    "class": "5B"
  },
  "progress": 100,
  "timePassed": 243120,
  "lastPlayedAt": 1758297843120,
  "createdAt": 1758297600000,
  "playerInput": {
    "-Nq8item_one": "Lisbon",
    "-Nq8item_two": "1969"
  },
  "correctUids": {
    "-Nq8item_one": true,
    "-Nq8item_two": false
  },
  "score": 800,
  "contentVersion": 1757923200000
}
Puuttuu, ei ole tyhjä

Kenttä, joka ei sovellu, jätetään pois JSON:sta sen sijaan, että se lähetettäisiin null-arvona tai nollana. Näin tyyppi, joka ei pisteytä pelikertaa, erotetaan pelikerrasta, joka pisteytyi nollaan — lue siis oletusarvolla äläkä koskaan oleta, että avain on olemassa.

Aktiviteetin nollaaminen sivultasi

Yksi komento kulkee toiseen suuntaan. Kun "Hyväksy komennot upottavalta sivulta" on kytketty päälle, upottava sivu voi tyhjentää pelaajan vastaukset ja palauttaa aktiviteetin alkuun — omaa "yritä uudelleen" -painiketta varten kehyksen ulkopuolella.

reset
const frame = document.querySelector('iframe').contentWindow;

// Sent to the frame, from the page that embeds it — no other sender is
// accepted, and the activity has to have the trigger setting switched on.
frame.postMessage({ trigger: { type: 'reset' } }, 'https://puzzel.org');
Nollaus on ainoa komento

Tuloksen lähettämiselle, lopetusviestin avaamiselle tai kysymykseen hyppäämiselle ei ole viestiä. Viesti, joka pyytää muuta kuin nollausta, jätetään huomiotta.

Vain upottavaa sivua kuunnellaan

Komento hyväksytään vain sivulta, joka kehystää aktiviteetin, eikä mistään muualta — ei sisarkehykseltä, ei sivulla olevalta skriptiltä. Asetus on oletuksena pois päältä, joten kytke se päälle niille aktiviteeteille, joita ohjaat.

Oman pelaajaidentiteetin tuominen mukaan

Jos alustasi jo tietää, kuka pelaa, aktiviteetin ei tarvitse kysyä sitä uudelleen. Kaksi kättelyä on olemassa, molemmat sivullesi upotettua aktiviteettia varten, ja molemmat me kytkemme päälle emmekä sinä editorista — ne muuttavat sen, kenelle tulos kuuluu, joten ne otetaan käyttöön yhdessä kanssasi, ei valintaruudusta.

Lähetä pelaaja meille

Aktiviteetti ilmoittautuu viestillä 'app-loaded' ja odottaa. Sivusi lähettää pelaajan tiedot takaisin, ja tulos tallennetaan hänen nimiinsä ilman, että pelaaja kirjoittaa mitään tai näkee rekisteröitymisnäyttöä.

Lähetä meille tunniste

Sama kättely, mutta sivusi lähettää identiteetintarjoajasi myöntämän JWT:n itse kenttien sijaan. Vahvistamme sen tilillesi määritettyjä myöntäjiä vasten, ennen kuin pelaaja päästetään sisään, joten identiteetti todistetaan eikä vain väitetä — tämä on se, jota kannattaa pyytää, kun tuloksen täytyy olla luotettava.

index.html
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://puzzel.org') return;

  // The activity says it is ready for a player.
  if (event.data === 'app-loaded') {
    frame.postMessage(
      {
        player: { name: 'Ava Ortega', email: 'ava@school.example', class: '5B' },
        // true starts a fresh attempt instead of resuming this player's last one
        should_reset: false
      },
      'https://puzzel.org'
    );
  }

  // Signed in; the board is coming.
  if (event.data?.success === true) hideYourOwnSpinner();
});
Pyydä meitä kytkemään se päälle

Kerro, kumman näistä kahdesta haluat ja mihin aktiviteetit upotetaan, niin otamme tilisi käyttöön ja käymme sen läpi kanssasi.

Lähetä meille sähköpostia identiteetistä

Aktiviteettien luominen omasta järjestelmästäsi

Kaikki edellä on tuloksesta, joka tulee ulos. Toiseen suuntaan — aktiviteettien tekeminen sisällöstä, joka sinulla jo on — on Puzzle API: yksi POST per aktiviteettityyppi, ja saat takaisin avaimen ja upotettavan URL-osoitteen.

Lue API-viitedokumentaatio

Kun valmis liitäntä on parempi vastaus

Jos toisella puolella on oikea LMS, et todennäköisesti tarvitse mitään tästä. Arvosanat voivat palautua sen arvosanataulukkoon itsestään, eikä sinun tarvitse isännöidä mitään.

Ei mikään noista?

Kurssialustat, jäsensivustot, intranetit ja mikä tahansa itse rakentamasi järjestelmä ovat juuri sitä varten, mitä tämän sivun kanavat tarjoavat. Upotus ja valmistumissignaali kattavat suurimman osan siitä.

Mitä ei ole

Ettet turhaan etsi näitä:

  • Ei päätepistettä tulosten lukemiseen takaisin. API luo aktiviteetteja; tulokset lähtevät tämän sivun kanavien kautta tai hallintapaneelisi vientien kautta.
  • Ei allekirjoitusta webhookissa. Ei ole mitään, mitä vasten pyyntö voisi tarkistaa, minkä vuoksi tuloksen ei pitäisi olla ainoa asia, joka kannattelee jotain tärkeää.
  • Ei tilinlaajuista webhookia. URL-osoite on aktiviteettikohtainen asetus, joten kopioimasi aktiviteetti kuljettaa sen mukanaan, ja uusi aktiviteetti aloittaa ilman sitä.
  • Ei mitään joukkuepelissä tai livehuoneessa. Molemmat viestikanavat ja webhook on tarkoitettu yksinpeliin, ja asetukset kytkeytyvät itse pois päältä, kun moninpeli on käytössä.
  • Ei toimitusjonoa. Mitään ei tallenneta ja lähetetä uudelleen — seuraava tallennus on uusintayritys, ja pelikerran viimeinen kutsu on se, joka ratkaisee.

Jokin ei toimi odotetusti?

Lähetä pyyntö, jota kokeilit, ja virhe, jonka sait vastaukseksi, niin saat oikean vastauksen henkilöltä, joka kirjoitti päätepisteen.

Lähetä sähköpostia tukeen