Utstedelse av Open Badges fra WordPress (uten et tungt plugin)
Utsted Open Badges fra ethvert WordPress-kurs/LMS-plugin (LearnDash, LifterLMS, Tutor) ved å kalle Badges Ninja API-et ved fullføring — ingen separat badge-plugin å installere.
Nacho founded Badges Ninja to make issuing verifiable digital credentials as simple as a single API call — Open Badge v2.0 badges and certificates, minted, hosted, and verifiable without standing up your own issuer infrastructure.
Hvis du kjører kurs på WordPress, kjenner du allerede rutinen: noen fullfører en modul i LearnDash, LifterLMS eller Tutor LMS, LMS-et markerer det som “fullført”, og så… skjer det ikke noe som kan verifiseres. Kanskje sender du en PDF på e-post. Kanskje installerer du et dedikert WordPress badge-plugin som legger til sine egne databasetabeller, sitt eget bildebibliotek og sin egen idé om hva et “badge” er — én som ingen utenfor nettstedet ditt kan verifisere.
Det finnes en enklere vei. WordPress-kursplugins utløser allerede en action hook i det øyeblikket noen fullfører et kurs. Du kan fange opp den hooken og gjøre ett HTTP-kall til Badges Ninja API-et. Ingen ekstra plugin, ingen ekstra hosting, intet proprietært badge-format — bare et standardkompatibelt Open Badge v2.0-akkreditiv som mottakeren din kan verifisere hvor som helst, legge til på LinkedIn og laste ned som PDF.
Dette innlegget går gjennom mønsteret én gang, og viser deretter det spesifikke hooket for LearnDash, LifterLMS og Tutor LMS.
Hvorfor ikke bare bruke et WordPress badge-plugin?
Dedikerte WordPress badge-plugins løser et smalere problem enn de ser ut til å løse. De er gode til å vise et bilde på en “mine prestasjoner”-side på nettstedet ditt. De er som regel mye svakere på det som faktisk betyr noe for et akkreditiv:
- Portabilitet. Et badge som bare finnes som en shortcode på WordPress-nettstedet ditt, er ikke et akkreditiv — det er en dekorasjon. I det øyeblikket mottakeren bytter jobb, bytter innboks, eller nettstedet ditt går ned, forsvinner “beviset” med det.
- Verifisering. Alle bør kunne sjekke at et akkreditiv er ekte uten å logge inn på WordPress-administrasjonen din. Open Badge v2.0 gir deg en offentlig verifiserings-URL og maskinlesbar JSON-LD som en del av designet.
- Vedlikeholdsflate. Hvert WordPress-plugin er enda en ting å patche, enda en databasetabell å sikkerhetskopiere, enda et feilpunkt under en kjerneoppdatering.
Å kalle et eksternt API ved kursfullføring omgår alle tre. WordPress forblir ansvarlig for det det er god til — innholdslevering og fremdriftssporing — og selve akkreditivet lever i et system bygget spesifikt for å utstede, verifisere og dele det.
Mønsteret: ett hook, ett HTTP-kall
Alle store WordPress LMS-plugins utløser en handling når en bruker fullfører et kurs. Integrasjonen er alltid de samme tre trinnene:
- Hook deg inn i fullføringshandlingen for ditt spesifikke LMS.
- Slå opp (eller opprett) mottakerens identitet — som regel bare WordPress-kontoens e-post og visningsnavn.
- Kall
POST /awardspå Badges Ninja API-et medwp_remote_post(), og send med badge-ID-en og mottakeropplysningene.
Du trenger en API-nøkkel først. Generer én fra dashbordet ditt under API Keys — se API keys guide for hele gjennomgangen. Nøkler vises bare én gang ved opprettelse, så lagre den i wp-config.php som en konstant i stedet for i databasen:
define( 'BADGES_NINJA_API_KEY', 'bws_your_32_hex_key_here' );
define( 'BADGES_NINJA_BADGE_ID', 'your-badge-id' );

Behold denne nøkkelen på serversiden. Alt i denne guiden kjører i PHP på WordPress-serveren din — wp_remote_post() er et serverside-kall, og wp-config.php sendes aldri til nettleseren. Det er akkurat det du vil ha: nøkkelen reiser server-til-server over HTTPS, og ingen besøkende på nettstedet kan lese den. Flytt aldri dette kallet inn i klientside-JavaScript — et fetch()-kall fra nettleseren med nøkkelen innebygd ville eksponere den for hvem som helst via nettleserens utviklerverktøy. To vaner er verdt å beholde: sørg for at hosten din serverer wp-config.php som utført PHP (aldri som ren tekst, og ikke la en wp-config.php.bak-kopi ligge i webroten), og opprett en dedikert API-nøkkel for denne integrasjonen, slik at du kan tilbakekalle den uavhengig hvis den noen gang blir kompromittert — uten å ødelegge de andre verktøyene dine.
En delt hjelpefunksjon holder hvert LMS-hook enkelt:
function badges_ninja_issue_award( $recipient_email, $recipient_name, $badge_id ) {
$response = wp_remote_post( 'https://api.badges.ninja/awards', array(
'headers' => array(
'X-Api-Key' => BADGES_NINJA_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'badgeId' => $badge_id,
'recipient' => array(
'name' => $recipient_name, // must be at least 5 characters
'email' => $recipient_email,
),
'issuedOn' => round( microtime( true ) * 1000 ), // epoch milliseconds
) ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
error_log( 'Badges Ninja award failed: ' . $response->get_error_message() );
return false;
}
$code = wp_remote_retrieve_response_code( $response );
if ( $code >= 400 ) {
error_log( 'Badges Ninja award failed with HTTP ' . $code . ': ' . wp_remote_retrieve_body( $response ) );
return false;
}
return json_decode( wp_remote_retrieve_body( $response ), true );
}
Mottakerens e-post blir SHA-256-hashet på serversiden så snart den når Badges Ninja, og svar-payloaden inneholder tildelingens verifiserings-URL — praktisk hvis du vil vise en “se akkreditivet ditt”-lenke rett der i WordPress etter at kallet har lyktes.
LearnDash
LearnDash utløser learndash_course_completed med et enkelt array-argument som inneholder user og course:
add_action( 'learndash_course_completed', function( $data ) {
$user = $data['user'];
$course = $data['course'];
// Map LearnDash course ID → your Badges Ninja badge ID.
// A simple approach: store the badge ID in a course custom field.
$badge_id = get_post_meta( $course->ID, 'badges_ninja_badge_id', true );
if ( ! $badge_id ) {
return; // no badge configured for this course
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Å lagre badge-ID-en som kursmetadata (i stedet for én global BADGES_NINJA_BADGE_ID-konstant) er det riktige valget når du har mer enn ett kurs — hvert kurs kobles til sitt eget badge-design.
LifterLMS
LifterLMS utløser lifterlms_course_completed med $user_id og $course_id:
add_action( 'lifterlms_course_completed', function( $user_id, $course_id ) {
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
}, 10, 2 );
Tutor LMS
Tutor LMS utløser tutor_course_complete_after med kurs-ID-en, og du henter gjeldende bruker fra økten:
add_action( 'tutor_course_complete_after', function( $course_id ) {
$user_id = get_current_user_id();
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Hvis Tutor LMS-oppsettet ditt utløser fullføring fra en bakgrunnsprosess (f.eks. via automatisk sensurering av en quiz), bytt ut get_current_user_id() med bruker-ID-en det spesifikke hooket ditt gir — sjekk payloaden med error_log( print_r( func_get_args(), true ) ) én gang under oppsettet for å bekrefte argumentene.
Design badget før du kobler til hooket
Før noe av dette utløses, trenger du et badge å tildele. Den visuelle designeren dekker dette uten at du trenger en designer ansatt — 80+ formmaler, egendefinerte farger, ikonbibliotek og logo-opplasting, alt med snap-to-grid. Hvis du er ny til designeren, går Design ditt første verifiserbare digitale sertifikat gjennom hvordan du velger en mal og leverer noe mottakerne faktisk vil dele.
Når badget finnes, henter du ID-en fra dashbordet (eller via GET /badges) og legger den inn i kursets egendefinerte felt.
Hva mottakeren faktisk får
Dette er delen et hjemmesnekret WordPress badge-plugin ikke kan gjenskape. Når POST /awards lykkes, får mottakeren:
- En unik verifiserings-URL hvem som helst kan åpne — ingen WordPress-innlogging nødvendig — som viser at akkreditivet er ekte, hvem som utstedte det, og når.
- En QR-kode og et A4 PDF-sertifikat, generert automatisk.
- En Legg til i LinkedIn-profil-knapp, hvis utstederen din har en LinkedIn-organisasjons-ID satt — se Legg til en LinkedIn “Legg til i profil”-knapp for engangsoppsettet.
- Tilgang til sin egen mottakerportal på
badges.ninja/me, via magic-link-innlogging — ikke noe passord å glemme, ingen egen konto å administrere på WordPress-nettstedet ditt. - Standardkompatibel Open Badge v2.0 JSON-LD, slik at enhver OB-bevisst verifikator (ikke bare Badges Ninja) kan validere det.
Ingenting av dette er WordPress sin jobb å bygge, og ingenting av det bør bare leve inne i WordPress-databasen din.
Håndtering av feil på en elegant måte
Kursfullførings-hooks utløses under en direkte sideforespørsel, og et treigt eller mislykket API-kall bør ikke blokkere elevens “gratulerer”-skjerm. To praktiske justeringer når du er kommet forbi et proof of concept:
Ikke la en mislykket tildeling blokkere brukergrensesnittet. Hjelpefunksjonen ovenfor logger allerede og returnerer false i stedet for å kaste en feil — LearnDash, LifterLMS og Tutor fortsetter alle sin normale fullføringsflyt uansett hva badges_ninja_issue_award() returnerer.
Sett det i kø i stedet for å kalle det direkte, i stor skala. Hvis du kjører store kull gjennom ett kurs samtidig (en kull-startdato, en frigivelse av webinar-opptak), utløs en planlagt WP-Cron-hendelse fra hooket i stedet for å kalle API-et synkront:
add_action( 'learndash_course_completed', function( $data ) {
wp_schedule_single_event( time() + 30, 'badges_ninja_deferred_award', array(
$data['user']->user_email,
$data['user']->display_name,
get_post_meta( $data['course']->ID, 'badges_ninja_badge_id', true ),
) );
} );
add_action( 'badges_ninja_deferred_award', 'badges_ninja_issue_award', 10, 3 );
Dette sprer belastningen og hindrer at én treg forespørsel blir elevens problem. For virkelig store batcher (et helt tidligere kull, migrert i én omgang), hopp over WordPress-hook-veien helt og bruk bulk-tildelinger via CSV — last opp én gang, så paginerer plattformen utstedelsen server-side med innebygd pause/gjenoppta.
En note om idempotens
Hvis LMS-et ditt noen gang utløser fullføringshooket sitt mer enn én gang for samme bruker (et vanlig LearnDash-særtilfelle med gjentatte quizforsøk, eller en Tutor LMS-resynkronisering), vil du ikke tildele samme badge to ganger. Den enkleste beskyttelsen er et WordPress user-meta-flagg du setter rett etter et vellykket kall:
if ( get_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true ) ) {
return; // already issued
}
$result = badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
if ( $result ) {
update_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true );
}
Hvis du utsteder i reelt volum og ønsker at dette håndteres sentralt i stedet for per nettsted, se på webhook-drevet hendelseshåndtering eller den fullstendige API-hurtigstarten for request/response-formene på tvers av alle endepunkter.
Når dette mønsteret vokser forbi ett kurs
Eksemplene ovenfor forutsetter ett badge per kurs. Når du begynner å kjøre stablbare akkreditiver — et sporbadge som låses opp etter flere kursbadges, eller et avsluttende badge som avhenger av flere forutsetninger — flytt kartleggingen av “hvilket badge, for hvilken fullføring” ut av post-metadata og inn i en liten oppslagstabell, eller styr den fra en regnearksbasert automatisering (Airtable eller Google Sheets) som utløser det samme POST /awards-kallet. Selve API-kallet endrer seg ikke; det er bare det som avgjør når det skal gjøres, som endrer seg.
Feilsøking av integrasjonen
En håndfull problemer står for det meste av friksjonen folk møter når de kobler dette opp for første gang:
Hooket utløses aldri. Bekreft at du hooker deg inn i riktig handling for pluginets faktiske versjon — særlig LearnDash har endret navn på fullførings-hooks på tvers av store utgivelser (eldre installasjoner er noen ganger fortsatt avhengige av at learndash_course_completed utløses fra en annen kodesti enn nyere gjør). Legg til en midlertidig error_log() øverst i callbacken din og følg med på wp-content/debug.log mens du fullfører et testkurs som en engangsbruker.
wp_remote_post() går i timeout. Delte hostingmiljøer blokkerer noen ganger utgående HTTPS til ukjente hoster, eller setter et tak for forespørsels-timeout under de 15 sekundene satt ovenfor. Hvis kall konsekvent går i timeout, sjekk med hosten din om utgående tilkoblinger til api.badges.ninja er tillatt, og bekreft at PHP curl-utvidelsen din har oppdaterte CA-sertifikater — en utdatert sertifikatpakke er en vanlig stille feil på eldre shared-hosting-stakker.
400 Bad Request. Payloaden mangler et påkrevd felt eller har feil form. POST /awards forventer badgeId, et nøstet recipient-objekt med name og email, og et issuedOn-tidsstempel — hjelpefunksjonen ovenfor sender akkurat det. Den vanligste fellen er mottakerens navn: det må være minst 5 tegn, så et WordPress-visningsnavn som “Jo” blir avvist. Fall tilbake til kontoens fulle navn (eller e-postens lokale del) når visningsnavnet er for kort.
401 Unauthorized. API-nøkkel-konstanten laster ikke, eller den ble regenerert etter at konstanten ble satt. Nøkler vises bare én gang ved opprettelse og kan ikke hentes igjen — hvis du har mistet oversikten over hvilken nøkkel som er aktiv, slett den utdaterte og utsted en ny i stedet for å gjette.
Badge utstedt, men til feil badge-design. Dette er nesten alltid en utdatert badges_ninja_badge_id post-metaverdi som er igjen fra testing. Fordi kartleggingen ligger på kurs-posten, er det lett å glemme at du endret den etter å ha duplisert et kurs for et nytt kull — verdt en rask sjekk hver gang du kloner et kurs.
Doble tildelinger til samme person. Dekket ovenfor med user-meta-beskyttelsen, men verdt å gjenta: LMS-fullførings-hooks er ikke garantert å utløses nøyaktig én gang. Behandle “allerede tildelt” som et normalt tilfelle å sjekke for, ikke et unntakstilfelle å ignorere.
Ofte stilte spørsmål
Fungerer dette med WooCommerce-kurspakker? Ja — hvis et pakkekjøp skal utløse et badge uavhengig av kursfullføring (f.eks. et “sertifisert medlem”-badge til alle som kjøper en bestemt pakke), hook deg inn i woocommerce_order_status_completed i stedet for en LMS-fullføringshandling, og slå opp badge-ID-en fra produktmetadata i stedet for et kurs.
Kan mottakere få badget uten en WordPress-konto? Ja, og det er hele poenget. Tildelingen er knyttet til e-postadressen deres i Badges Ninja, ikke til en WordPress-brukerpost. Hvis nettstedet ditt tillater gjestekjøp eller anonym quizfullføring, sørg bare for at du fanger opp en ekte e-postadresse å sende inn i badges_ninja_issue_award().
Hva om jeg vil gjennomgå tildelinger før de sendes ut? Ikke utløs kallet direkte fra fullføringshooket. Skriv i stedet den ventende tildelingen (bruker, kurs, tidsstempel) til en egendefinert tabell eller posttype, og utsted den fra en planlagt oppgave eller en admin-knapp “Godkjenn og tildel” som kaller den samme hjelpefunksjonen ved behov.
Trenger jeg et eget badge per kurs, eller kan ett badge dekke flere? Begge deler fungerer. Noen utstedere lager ett badge per kurs for detaljnivå; andre lager ett samlet “programfullføring”-badge og tildeler det først når alle påkrevde kurs er fullført, ved å sjekke fullføring av forutsetninger inne i hooket før API-et kalles.
Klar til å utstede ditt første verifiserbare akkreditiv? Start gratis på badges.ninja — visuell designer, offentlig verifiseringsside, PDF-sertifikat, Open Badge v2.0-utdata. Ikke noe kredittkort nødvendig.
Slik ble denne artikkelen laget
Enkelte innlegg på denne bloggen er utarbeidet med hjelp av en KI-assistent, og deretter gjennomgått, faktasjekket og redigert av Badges Ninja-teamet før publisering. Alle kodeeksempler og priser er verifisert mot det faktiske produktet. Les mer om vår redaksjonelle prosess og KI-bruk på vår side om redaksjonell prosess .

Om forfatteren
Nacho Coll
Founder & Engineer at Badges Ninja
Nacho founded Badges Ninja to make issuing verifiable digital credentials as simple as a single API call — Open Badge v2.0 badges and certificates, minted, hosted, and verifiable without standing up your own issuer infrastructure. Writes about the Open Badges spec, credential verification, and running a credentialing platform serverless on AWS, from the operator side of the wire.
