Vydávání Open Badges z WordPressu (bez těžkého pluginu)
Vydávejte Open Badges z jakéhokoli pluginu pro kurzy/LMS na WordPressu (LearnDash, LifterLMS, Tutor) voláním API Badges Ninja po dokončení kurzu — bez instalace samostatného pluginu na odznaky.
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.
Pokud provozujete kurzy na WordPressu, už tenhle scénář znáte: někdo dokončí modul v LearnDash, LifterLMS nebo Tutor LMS, LMS ho označí jako “dokončeno” a pak… se nic ověřitelného nestane. Možná pošlete e-mailem PDF. Možná nainstalujete dedikovaný plugin na odznaky pro WordPress, který si přidá vlastní tabulky v databázi, vlastní knihovnu obrázků a vlastní představu o tom, co je to “odznak” — takovou, kterou nikdo mimo váš web neověří.
Existuje jednodušší cesta. Pluginy pro kurzy na WordPressu už ve chvíli, kdy někdo dokončí kurz, spouští action hook. Tento hook můžete zachytit a provést jedno HTTP volání na API Badges Ninja. Žádný další plugin, žádný další hosting, žádný proprietární formát odznaku — jen standardizované pověření Open Badge v2.0, které si váš příjemce může kdekoli ověřit, přidat na LinkedIn a stáhnout jako PDF.
Tento článek nejprve projde vzor jednou obecně a poté ukáže konkrétní hook pro LearnDash, LifterLMS a Tutor LMS.
Proč prostě nepoužít plugin na odznaky pro WordPress?
Dedikované pluginy na odznaky pro WordPress řeší užší problém, než se na první pohled zdá. Umí dobře vykreslit obrázek na stránce “moje úspěchy” uvnitř vašeho webu. U věcí, na kterých u pověření skutečně záleží, jsou obvykle mnohem slabší:
- Přenositelnost. Odznak, který existuje jen jako shortcode na vašem webu WordPress, není pověření — je to dekorace. Ve chvíli, kdy příjemce změní zaměstnání, změní e-mailovou schránku, nebo váš web spadne, “důkaz” zmizí s ním.
- Ověření. Kdokoli by měl mít možnost zkontrolovat, že je pověření skutečné, aniž by se přihlašoval do administrace vašeho WordPressu. Open Badge v2.0 vám ze své podstaty dává veřejnou URL pro ověření a strojově čitelný JSON-LD.
- Plocha údržby. Každý plugin WordPress je další věc, kterou je třeba patchovat, další databázová tabulka k zálohování, další bod selhání při aktualizaci jádra.
Volání externího API při dokončení kurzu všechny tři problémy obejde. WordPress zůstává zodpovědný za to, v čem je dobrý — doručování obsahu a sledování postupu — a samotné pověření žije v systému postaveném speciálně pro jeho vydávání, ověřování a sdílení.
Vzor: jeden hook, jedno HTTP volání
Každý větší plugin LMS pro WordPress spouští akci, když uživatel dokončí kurz. Integrace se vždy skládá ze stejných tří kroků:
- Napojte se na akci dokončení pro váš konkrétní LMS.
- Vyhledejte (nebo vytvořte) identitu příjemce — obvykle jen e-mail jeho účtu WordPress a zobrazované jméno.
- Zavolejte
POST /awardsna API Badges Ninja pomocíwp_remote_post()s předáním ID odznaku a údajů o příjemci.
Nejprve budete potřebovat API klíč. Vygenerujte si ho v dashboardu pod API Keys — kompletní postup najdete v průvodci API klíči. Klíče se zobrazí jen jednou při vytvoření, takže ho uložte do wp-config.php jako konstantu, ne do databáze:
define( 'BADGES_NINJA_API_KEY', 'bws_your_32_hex_key_here' );
define( 'BADGES_NINJA_BADGE_ID', 'your-badge-id' );

Tento klíč držte na straně serveru. Vše v tomto průvodci běží v PHP na vašem serveru WordPress — wp_remote_post() je serverové volání a wp-config.php se nikdy neodesílá do prohlížeče. Přesně to chcete: klíč cestuje server-server přes HTTPS a žádný návštěvník webu si ho nemůže přečíst. Nikdy toto volání nepřesouvejte do klientského JavaScriptu — fetch() z prohlížeče s vloženým klíčem by ho vystavil komukoli přes vývojářské nástroje prohlížeče. Stojí za to dodržovat dva zvyky: ujistěte se, že váš hosting servíruje wp-config.php jako spouštěné PHP (nikdy jako čistý text, a nenechávejte v kořenovém adresáři kopii wp-config.php.bak), a vytvořte pro tuto integraci vyhrazený API klíč, abyste ho mohli nezávisle zneplatnit, pokud by byl někdy kompromitován — bez narušení vašich ostatních nástrojů.
Sdílená pomocná funkce udržuje každý hook LMS tenký:
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 );
}
E-mail příjemce je na straně serveru zahašovaný algoritmem SHA-256, jakmile dorazí do Badges Ninja, a vrácená odpověď obsahuje URL pro ověření odměny — hodí se, pokud chcete po úspěšném volání hned ve WordPressu zobrazit odkaz “zobrazit své pověření”.
LearnDash
LearnDash spouští learndash_course_completed s jediným argumentem typu pole obsahujícím user a 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 );
} );
Uložení ID odznaku jako metadat kurzu (namísto jediné globální konstanty BADGES_NINJA_BADGE_ID) je správná volba ve chvíli, kdy máte více než jeden kurz — každý kurz se mapuje na vlastní design odznaku.
LifterLMS
LifterLMS spouští lifterlms_course_completed s $user_id a $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 spouští tutor_course_complete_after s ID kurzu a aktuálního uživatele si vytáhnete ze session:
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 );
} );
Pokud vaše nastavení Tutor LMS spouští dokončení z procesu na pozadí (např. přes automatické hodnocení testu), nahraďte get_current_user_id() ID uživatele, které poskytuje váš konkrétní hook — při nastavování jednou ověřte payload pomocí error_log( print_r( func_get_args(), true ) ), abyste potvrdili argumenty.
Návrh odznaku před napojením hooku
Než se cokoli z toho spustí, potřebujete odznak, který uděláte. Vizuální designer to pokrývá bez nutnosti mít v týmu designéra — přes 80 šablon tvarů, vlastní barvy, knihovna ikon a nahrání loga, vše s přichytáváním k mřížce. Pokud s designerem začínáte, Návrh vašeho prvního ověřitelného digitálního certifikátu vás provede výběrem šablony a vytvořením něčeho, co příjemci opravdu budou chtít sdílet.
Jakmile odznak existuje, vezměte si jeho ID z dashboardu (nebo přes GET /badges) a vložte ho do vlastního pole kurzu.
Co příjemce skutečně dostane
Tohle je část, kterou domácí plugin na odznaky pro WordPress nedokáže replikovat. Když POST /awards uspěje, příjemce dostane:
- Jedinečnou URL pro ověření, kterou může otevřít kdokoli — bez nutnosti přihlášení do WordPressu — a která ukazuje, že pověření je skutečné, kdo ho vydal a kdy.
- QR kód a PDF certifikát ve formátu A4, generované automaticky.
- Tlačítko Add to LinkedIn Profile, pokud má váš vydavatel nastavené ID organizace na LinkedIn — jednorázové nastavení najdete v Přidání tlačítka LinkedIn “Add to Profile”.
- Přístup do vlastního portálu příjemce na
badges.ninja/mepřes přihlášení magic-linkem — žádné heslo k zapomenutí, žádný samostatný účet ke správě na vašem webu WordPress. - Standardizovaný Open Badge v2.0 JSON-LD, takže ho může ověřit jakýkoli ověřovatel podporující OB (nejen Badges Ninja).
Nic z toho není úkolem WordPressu, a nic z toho by nemělo žít pouze ve vaší databázi WordPress.
Elegantní zvládání selhání
Hooky dokončení kurzu se spouští během živého požadavku na stránku a pomalé nebo neúspěšné volání API by nemělo blokovat “gratulační” obrazovku studenta. Dvě praktické úpravy, jakmile se posunete za proof of concept:
Nedovolte, aby neúspěšná odměna blokovala UI. Výše uvedená pomocná funkce už loguje a vrací false místo vyhazování výjimky — LearnDash, LifterLMS i Tutor pokračují ve svém běžném toku dokončení bez ohledu na to, co vrátí badges_ninja_issue_award().
Ve větším měřítku dávejte do fronty, místo volání inline. Pokud najednou provádíte velké kohorty jedním kurzem (datum startu kohorty, odemčení záznamu webináře), spusťte z hooku naplánovanou událost WP-Cron místo synchronního volání API:
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 );
Tím se rozloží zátěž a jeden pomalý požadavek se nestane problémem studenta. U opravdu velkých dávek (celá minulá kohorta, migrovaná najednou) přeskočte cestu přes hook WordPress úplně a použijte hromadné udílení odměn přes CSV — nahrajte jednou a platforma vydávání stránkuje na straně serveru, s vestavěnou pauzou a obnovením.
Poznámka k idempotenci
Pokud váš LMS někdy spustí svůj hook dokončení víckrát pro stejného uživatele (běžný okrajový případ v LearnDash s opakovaným pokusem o test, nebo resynchronizace v Tutor LMS), nechcete udělit stejný odznak dvakrát. Nejjednodušší pojistkou je příznak v user-meta WordPress, který nastavíte hned po úspěšném volání:
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 );
}
Pokud vydáváte ve skutečně velkém objemu a chcete to řešit centrálně místo po jednotlivých webech, podívejte se na zpracování událostí přes webhooky nebo kompletní rychlý start API s tvary požadavků a odpovědí pro každý endpoint.
Když tento vzor přeroste jediný kurz
Výše uvedené příklady předpokládají jeden odznak na kurz. Jakmile začnete provozovat vrstvená pověření — odznak trasy, který se odemkne po několika odznacích kurzů, nebo závěrečný odznak závisející na více předpokladech — přesuňte mapování “který odznak, za jaké dokončení” z meta příspěvku do malé vyhledávací tabulky, nebo ho řiďte automatizací postavenou na tabulce (Airtable nebo Google Sheets), která spouští stejné volání POST /awards. Samotné volání API se nemění; mění se jen to, co rozhoduje, kdy ho provést.
Řešení problémů s integrací
Za většinu potíží, na které lidé narazí při prvním zapojování, může hrstka problémů:
Hook se nikdy nespustí. Ověřte, že se napojujete na správnou akci pro skutečnou verzi svého pluginu — LearnDash zejména mezi hlavními vydáními měnil názvy hooků dokončení (starší instalace se občas stále spoléhají na learndash_course_completed spouštěný z jiné cesty kódu než ty novější). Přidejte dočasný error_log() na začátek svého callbacku a sledujte wp-content/debug.log, zatímco jako jednorázový uživatel dokončíte testovací kurz.
wp_remote_post() vyprší časový limit. Prostředí sdíleného hostingu někdy blokují odchozí HTTPS na neznámé hosty nebo omezují časový limit požadavku pod výše nastavených 15 sekund. Pokud volání trvale vyprší, ověřte se svým hostingem, zda jsou povolena odchozí spojení na api.badges.ninja, a potvrďte, že vaše PHP rozšíření curl má aktuální CA certifikáty — zastaralý balíček certifikátů je běžné tiché selhání na starších sdílených hostingových stacích.
400 Bad Request. V payloadu chybí povinné pole nebo má špatný tvar. POST /awards očekává badgeId, vnořený objekt recipient s name a email a časové razítko issuedOn — výše uvedená pomocná funkce posílá přesně to. Nejčastějším zádrhelem je jméno příjemce: musí mít alespoň 5 znaků, takže zobrazované jméno WordPressu jako “Jo” bude odmítnuto. Pokud je zobrazované jméno příliš krátké, použijte jako záložní variantu celé jméno z účtu (nebo lokální část e-mailu).
401 Unauthorized. Konstanta API klíče se nenačítá, nebo byl klíč po nastavení konstanty znovu vygenerován. Klíče se zobrazí jen jednou při vytvoření a nelze je znovu získat — pokud jste ztratili přehled o tom, který klíč je aktivní, smažte ten starý a vydejte nový, místo abyste hádali.
Odznak udělen, ale se špatným designem odznaku. Téměř vždy jde o zastaralou hodnotu post-meta badges_ninja_badge_id, která zůstala z testování. Protože mapování žije na příspěvku kurzu, snadno se zapomene, že jste ho po duplikování kurzu pro novou kohortu změnili — stojí za to to rychle zkontrolovat pokaždé, když kurz klonujete.
Duplicitní odměny pro stejnou osobu. Probráno výše u pojistky přes user-meta, ale stojí za zopakování: hooky dokončení LMS nemají zaručeno, že se spustí přesně jednou. Berte “již uděleno” jako běžný případ ke kontrole, ne jako okrajový případ, který lze ignorovat.
Často kladené otázky
Funguje to s balíčky kurzů WooCommerce? Ano — pokud má nákup balíčku spustit odznak nezávisle na dokončení kurzu (např. odznak “certifikovaný člen” pro každého, kdo koupí konkrétní balíček), napojte se na woocommerce_order_status_completed místo akce dokončení LMS a ID odznaku vezměte z meta produktu, ne z kurzu.
Mohou příjemci dostat odznak bez účtu WordPress? Ano, a o to jde. Odměna je navázaná na jejich e-mailovou adresu v Badges Ninja, ne na záznam uživatele WordPress. Pokud váš web umožňuje nákup jako host nebo anonymní dokončení testu, jen se ujistěte, že zachytáváte skutečnou e-mailovou adresu k předání do badges_ninja_issue_award().
Co když chci odměny před odesláním zkontrolovat? Vynechte přímé volání z hooku dokončení. Místo toho zapište čekající odměnu (uživatel, kurz, časové razítko) do vlastní tabulky nebo typu příspěvku a udělte ji z naplánované úlohy nebo administrátorského tlačítka “Schválit a udělit”, které na vyžádání volá stejnou pomocnou funkci.
Potřebuji samostatný odznak pro každý kurz, nebo může jeden pokrýt více kurzů? Funguje obojí. Někteří vydavatelé vytvářejí jeden odznak na kurz kvůli granularitě; jiní vytvoří jediný odznak “dokončení programu” a udělí ho až po dokončení všech povinných kurzů, přičemž dokončení předpokladů kontrolují uvnitř hooku před voláním API.
Připraveni vydat své první ověřitelné pověření? Začněte zdarma na badges.ninja — vizuální designer, veřejná stránka pro ověření, PDF certifikát, výstup Open Badge v2.0. Bez kreditní karty.
Jak tento článek vznikl
Některé příspěvky na tomto blogu vznikají s pomocí AI asistenta a před publikováním je kontroluje, ověřuje a upravuje tým Badges Ninja. Každá ukázka kódu a cena je ověřena oproti aktuálnímu produktu. Více o našem redakčním a AI procesu najdete na naší stránce o redakčním procesu .

O autorovi
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.
