Vóór WordPress 7.0 moest elke plugin die AI-features toevoegde zelf een API-sleutel opvragen en beheren om met een AI-provider te kunnen communiceren.
Dat kostte onnodig veel code en onderhoud. Je nam zware SDK-bibliotheken van providers op in je plugins en schreef cURL-verzoeken die per provider verschilden.
Met de native AI-integratie in WordPress 7.0 is die versnippering verleden tijd. WordPress heeft nu één centraal scherm waarin je de inloggegevens van verschillende AI-providers instelt, plus een nieuwe PHP-API. Daarmee stuur je prompts, instructies, mediabestanden en datastructuren door, terwijl WordPress Core de verzoeken afhandelt.
De nieuwe architectuur levert zowel sitebeheerders als plugin-ontwikkelaars flinke voordelen op.
Beheerders stellen AI niet langer per plugin apart in. Vanaf WordPress 7.0 installeer en activeer je je connector-plugins, voer je je API-sleutels in in het Connectors-scherm en zijn ze meteen beschikbaar voor elke plugin met AI-features op je site. Je houdt het AI-gebruik bij, wisselt van model of trekt de toegang van een provider voor alle plugins in met één klik.
Voor plugin-ontwikkelaars is de winst nóg groter: betere gegevensbeveiliging, overdraagbare code en een stuk minder technische schuld.
Tijd om de nieuwe AI-architectuur van WordPress van dichtbij te bekijken.
De drie lagen van de WordPress AI-architectuur
Je WordPress-sites zijn tegenwoordig standaard klaar voor AI. Niet met kant-en-klare AI-features, maar met de basis waarop je AI-functionaliteit bouwt.
De nieuwe architectuur bestaat uit drie lagen:
AI-connector
Vóór WordPress 7.0 had elke plugin met AI-features een eigen systeem nodig om je API-sleutels op te slaan en te beheren. Je inloggegevens stonden hardcoded in de plugin of werden beheerd via een custom instellingenpagina. Geen van beide is een prettige manier om met gevoelige gegevens om te gaan.

In één centraal scherm stel je al je AI-providers in. Dat levert een paar duidelijke voordelen op voor het beheer van je site.
Voor beheer en beveiliging is het grootste voordeel dat je je providers één keer instelt in het Connectors-scherm en er daarna geen omkijken meer naar hebt, hoeveel plugins er ook gebruik van maken. Moet je je API-sleutels wijzigen? Dan werk je ze in één keer bij in het Connectors-scherm, in plaats van plugin voor plugin.
Centrale opslag van inloggegevens maakt je site ook veiliger: gevoelige gegevens liggen niet langer verspreid over plugins van derden die slecht geschreven of onbetrouwbaar kunnen zijn.
Daarnaast wordt je code overdraagbaar. Je plugins hoeven niet te weten welke AI-provider je gebruikt, want de nieuwe architectuur trekt authenticatie los van de pluginlogica. Wissel je van AI-provider, dan blijft je plugin gewoon werken zonder dat je één regel code aanpast.
De echte doorbraak zit erin dat sitebeheerders meerdere connectors tegelijk kunnen instellen. Stuurt een plugin een verzoek, dan kiest WordPress zelf de meest geschikte AI-provider en het meest geschikte model voor het antwoord, op basis van de configuratie van de plugin en de mogelijkheden van de beschikbare modellen.
AI Client
Waar het Connectors-scherm de configuratie van AI-providers regelt, geeft de AI Client ontwikkelaars de tool om met AI-modellen te werken.
Het is een native interface die de communicatie met AI-modellen standaardiseert via de globale functie wp_ai_client_prompt() en een vaste set PHP-methoden.
Minder technische schuld
Voor ontwikkelaars zit het grootste voordeel in minder technische schuld en minder afhankelijkheden. Vóór WordPress 7.0 betaalde je voor AI-features een hoge prijs in onderhoud. Je bundelde SDK’s van derden (zoals de officiële bibliotheken van OpenAI of Anthropic) en hield doorlopend de versies in de gaten. Dat maakte je plugin zwaar en compatibiliteitsproblemen waarschijnlijk.
Daar kwamen nog eens veel regels code bij voor de netwerklogica en het parsen van antwoorden. Die code was bovendien providerspecifiek: wisselde je van AI-provider, dan herschreef je de complete netwerklaag van je plugin.
De AI Client haalt dat probleem bij de wortel weg door het zware werk naar WordPress Core te verplaatsen. Je code wordt volledig providerneutraal: je schrijft je instructies één keer en WordPress vertaalt ze naar het ‘dialect’ van het model.
Intelligente modelselectie
Een sterk punt van de fluent interface van de AI Client is dat je voorkeursmodellen instelt met de methode using_model_preference(), beschikbaar via de builderfunctie wp_ai_client_prompt(). Daarmee geef je een geordende lijst met modellen op voor de specifieke taak van je plugin. De code hieronder vraagt bijvoorbeeld tekstgeneratie aan met drie voorkeursmodellen:
$text_result = wp_ai_client_prompt( 'Convert the following transcript into a concise, blog-ready draft.' )
->using_model_preference(
'gemini-2.5-flash',
'claude-3-5-sonnet',
'gpt-4o'
)
->generate_text();
WordPress kijkt naar de providers in het Connectors-scherm, loopt de modellen uit je plugincode af en pakt de eerste connector die ook op de site beschikbaar is. Is geen van je opgegeven modellen beschikbaar onder de actieve Connectors, dan negeert WordPress je voorkeurslijst en valt het terug op het eerste compatibele model dat op de site is ingesteld.
Zo blijft je plugin werken, ook als de sitebeheerder overstapt naar een andere AI-provider.
AI-provider
Een AI-provider is het bedrijf dat de large language models (LLM’s) die we dagelijks gebruiken bezit, traint en host. OpenAI, Google Gemini en Anthropic zijn de bekendste AI-providers waarvoor WordPress 7.0 aparte connectors ondersteunt, maar ontwikkelaars kunnen ook zelf extra custom providers registreren.
Roept je plugincode de methode generate_text() aan, of een andere generatiemethode, dan bundelt WordPress de gegevens en stuurt die via het endpoint van de connector naar de AI-provider. Achter de schermen gebeurt dit:
- Allereerst ontvangt de AI-provider de invoertekst plus eventuele mediabestanden (de payload).
- De provider verwerkt het verzoek en past daarbij eventuele systeeminstructies toe.
- Vervolgens genereert hij de output, als vrije tekst of als JSON-object.
- Ten slotte stuurt hij de output via een HTTP-respons terug naar WordPress.
Elke provider biedt een breed scala aan modellen met verschillende mogelijkheden, snelheden en prijzen. Denk hierbij aan modellen die alleen tekst verwerken, multimodale modellen die naast een tekstprompt ook mediabestanden (audio, afbeeldingen, video) accepteren, en modellen voor specifieke taken zoals het genereren van afbeeldingen of spraak-naar-tekst.

Welke modellen beschikbaar zijn op een WordPress-site hangt dus af van de AI-providers die je instelt in het Connectors-scherm. Je plugin bepaalt niet welke provider er wordt gebruikt.
De functie wp_ai_client_prompt() van dichtbij
Met de functie wp_ai_client_prompt() communiceren plugins op een gestandaardiseerde manier met AI-modellen: geen externe bibliotheken, geen providerspecifieke configuratie en geen handmatige HTTP-verzoeken in je code.
Je schrijft je code één keer, waarna WordPress het zware werk overneemt en je instructies vertaalt naar het ‘dialect’ van elk model.
De functie geeft een instantie terug van de klasse WP_AI_Client_Prompt_Builder, met een fluent interface van methoden die je aan elkaar koppelt om je prompt op te bouwen. De klasse wordt als volgt beschreven:
/**
* Fluent builder for constructing AI prompts, returning WP_Error on failure.
*
* This class provides a fluent interface for building prompts with various
* content types and model configurations. It wraps the PHP AI Client SDK's
* PromptBuilder and adds WordPress-specific behavior including WP_Error
* handling instead of exceptions, snake_case method naming, and integration
* with the Abilities API.
*
* Only the generating methods will return a WP_Error, to not break the fluent
* interface. As soon as any exception is caught in a chain of method calls,
* the returned instance will be in an error state, and all subsequent method
* calls will be no-ops that just return the same error state instance. Only
* when a generating method is called, the WP_Error will be returned.
*/
wp_ai_client_prompt() voert zelf geen HTTP-verzoek uit. De functie maakt een WP_AI_Client_Prompt_Builder-object aan en geeft dat terug. Meer dan 50 configuratiemethoden vullen de private eigenschappen van dat object via een fluent interface, waardoor de code goed leesbaar en makkelijk te schrijven blijft.
Een greep uit de methoden die je het vaakst zult gebruiken:
with_text(): Voegt tekst toe aan het huidige bericht.with_file(): Voegt een bestand toe aan het huidige bericht.with_history(): Voegt berichten uit de gespreksgeschiedenis toe.using_model_preference(): Stelt de voorkeursmodellen in, in de volgorde waarin ze worden geëvalueerd.using_system_instruction(): Stelt de systeeminstructie in.using_max_tokens(): Stelt het maximale aantal te genereren tokens in.using_temperature(): Stelt de temperatuur voor de generatie in.using_top_p(): Stelt de top-p-waarde voor de generatie in.using_top_k(): Stelt de top-k-waarde voor de generatie in.as_output_file_type(): Stelt het type uitvoerbestand in.as_json_response(): Configureert de prompt voor een JSON-respons.is_supported_for_text_generation(): Controleert of de actieve configuratie tekstgeneratie ondersteunt.is_supported_for_image_generation(): Controleert of de actieve configuratie het genereren van afbeeldingen ondersteunt.is_supported_for_text_to_speech_conversion(): Controleert of de actieve configuratie tekst-naar-spraak ondersteunt.is_supported_for_video_generation(): Controleert of de actieve configuratie het genereren van video’s ondersteunt.generate_text(): Genereert een tekstresultaat op basis van de prompt.generate_image(): Genereert een afbeelding op basis van de prompt.convert_text_to_speech(): Zet tekst om in spraak.generate_speech(): Genereert spraak op basis van de prompt.generate_video(): Genereert een video op basis van de prompt.
Bekijk de broncode van WordPress Core voor de volledige lijst met methoden.
Stel dat je een audiobestand nauwkeurig wilt transcriberen. Dan gebruik je de functie zo:
$transcription_builder = wp_ai_client_prompt( $prompt )
->with_file( $audio_base64, $mime_type )
->using_temperature( 0.1 );
if ( ! $transcription_builder->is_supported_for_text_generation() ) {
// No configured provider supports the current prompt configuration.
return new WP_Error(
'no_supported_model',
'No configured AI model can process this request. Configure a provider in Settings > Connectors.',
array( 'status' => 400 )
);
}
$transcript = $transcription_builder->generate_text();
Wat deze code doet:
$prompt: de string met je belangrijkste instructies.with_file(): schakelt de multimodale mogelijkheden van de interface in. In het voorbeeld hierboven geven we de binaire audio door als Base64-string, samen met het bijbehorende MIME-type.using_temperature(): bepaalt hoe deterministisch het antwoord is. Een lage waarde (0,1) houdt het model dicht bij de audio, een hogere waarde geeft meer creatieve vrijheid. Combineer deze methode metusing_top_p()(top probability) voor meer controle over de output.is_supported_for_text_generation(): controleert of de actieve connectors voldoen aan de eisen van de huidige prompt, vóórdat je resources besteedt aan een netwerkverzoek.generate_text(): de afsluitende methode van de fluent interface. Die stuurt het samengestelde HTTP-verzoek naar de actieve provider en geeft de gegenereerde tekst terug, of eenWP_Error-object als het misgaat.
Samengevat: we sturen de AI-provider een tekstprompt met een audiobestand, zetten de temperatuur laag voor een zo deterministisch mogelijk resultaat, controleren of de actieve configuratie tekstgeneratie ondersteunt en halen de transcriptie uit het antwoord van de AI.
Met een tweede prompt sturen we het ruwe transcript terug naar de AI, voor een antwoord in de vorm van een JSON-object:
$structured_json = wp_ai_client_prompt(
"Convert the following transcript into a concise, blog-ready draft in American English.\n" .
"Return JSON with a post title and body sections.\n" .
"Each section must have: heading, level (2 or 3), and paragraphs (array).\n" .
"If useful, include bullet_points (array) for short actionable lists.\n" .
"Use short, clear headings and readable paragraph text.\n\n" .
"Transcript:\n" . $transcript
)
->using_system_instruction( "You are a professional WordPress content editor. Always write in American English (use appropriate spelling, grammar, and conventions for that language variant)." )
->using_temperature( 0.4 )
->as_json_response( $schema )
->generate_text();
In deze tweede prompt gebruiken we extra methoden om andere mogelijkheden van de API te benutten:
using_system_instruction(): bepaalt de context en de rol van het model, en scheidt de persona (‘een professionele WordPress-contentredacteur’) duidelijk van de data.using_temperature( 0.4 ): zet de temperatuur hoger dan bij de transcriptie, zodat het model een rijkere woordenschat gebruikt en vlottere content produceert.as_json_response(): dwingt het model een JSON-string terug te geven die overeenkomt met de structuur uit je$schema-variabele. Handig als je content voorbereidt voor Gutenberg.
Met output in JSON haal je losse velden eruit en koppel je die programmatisch aan native Gutenberg-blokken, met standaard WordPress-functies.
Een uitgebreider overzicht van de AI Client vind je in de dev note ‘Introducing the AI Client in WordPress 7.0’.
Zet een audiobestand met AI om in Gutenberg-ready content
Nu de drie lagen van de WordPress AI-architectuur duidelijk zijn, zetten we ze in een praktijkvoorbeeld. In dit deel bouw je de kernlogica van een plugin die uit een audiobestand rechtstreeks een goed opgebouwd conceptartikel genereert.
De toepassingen zijn breed. Denk hierbij aan een volledig artikel op basis van een kort spraakbericht uit je berichtenapp, of aan een interview dat je met je telefoon hebt opgenomen en laat transcriberen.
Voor deze functionaliteit bouw je een custom plugin. De standaardbestanden en het volledige registratieproces slaan we hier over; voor de basis van plugin-ontwikkeling kun je terecht bij andere tutorials op de Kinsta-blog of bij de officiële documentatie van WordPress.org.
We richten ons op de kernlogica waarmee je plugin met je AI-provider communiceert. De volledige plugin kun je bekijken en downloaden in deze GitHub-repository.
Wat deze plugin doet
Ga om te beginnen naar de GitHub-projectpagina en download het ZIP-bestand van de plugin. Log daarna in op je WordPress 7.0-dashboard en upload het via Plugins > Add plugin > Upload plugin. Zodra de plugin is geïnstalleerd en geactiveerd, kun je deze tutorial volgen.
De AI Content Builder-plugin voegt een custom instellingenzijbalk toe, die je opent via het icoon rechtsboven in de blokeditor. In die zijbalk zit een uploadveld voor audiobestanden en een schakelaar waarmee je de AI de huidige artikeltitel laat overschrijven.

De knop Upload Audio opent de media-uploader van WordPress. Daar upload je een nieuw audiobestand of kies je een bestaand bestand uit je mediabibliotheek.

Zodra het audiobestand is geladen, stuurt de knop Generate Content een asynchroon verzoek naar je actieve AI-provider.

De afbeelding hieronder toont het conceptartikel dat de AI in een paar seconden genereerde.

De resulterende content is opgebouwd uit native Gutenberg-blokken: alinea’s, koppen en lijsten.

Nu de logica van de plugin.
Wat je nodig hebt voor deze plugin
Dit heb je nodig om een WordPress-plugin te bouwen die via de nieuwe AI-architectuur je artikelcontent genereert:
- WordPress 7.0+
- Een API-sleutel van een AI-provider met een model dat spraak naar tekst omzet. In ons voorbeeld gebruiken we Google AI.
- Je favoriete IDE. Voor deze plugin gebruikten we VS Code.
- Gedegen kennis van ontwikkelen voor WordPress en Gutenberg, REST-API’s, PHP en JavaScript.
Node.js, buildprocessen of externe bibliotheken heb je niet nodig: de plugin draait volledig op de native API’s van WordPress Core. Het resultaat is een lichte, veilige plugin zonder technische schuld.
Structuur van de plugin en minimale WordPress-versie
De AI Content Builder-plugin bestaat uit twee bestanden:
ai-content-builder.phpeditor.js
De minimaal vereiste WordPress-versie is 7.0. Zet dat dus goed in de header van de plugin:
<?php
/**
* Plugin Name: AI Content Builder
* Description: Gutenberg sidebar plugin that uploads audio and generates post content using the WordPress 7.0 AI Client.
* Version: 1.0.0
* Requires at least: 7.0
* Requires PHP: 8.0
* Author: Your Name
* License: GPL-2.0-or-later
* Text Domain: ai-content-builder
*/
Met dat op zijn plek kijken we naar het bouwproces van een plugin met AI-features voor WordPress.
De datastroom van de plugin
Voordat we de code in duiken, eerst de route die de data aflegt: van de WordPress-backend (de blokeditor) naar de PHP-server en de AI-provider, en weer terug.
1. Van browser naar server: asynchrone REST-call: de browser stuurt de audio-ID naar het custom REST-endpoint van de plugin. Om te voorkomen dat de interface blokkeert, registreren we een REST-endpoint dat asynchrone verzoeken naar de PHP-server toestaat.
2. Eerste AI-ronde: spraak-naar-tekst: de server vangt het verzoek op, haalt de audio uit de database en vraagt de AI Client om de ruwe transcriptie.
3. Tweede AI-ronde: content structureren: de server stuurt de ruwe transcriptie terug naar de AI Client, met het verzoek er een gestructureerd JSON-object van te maken.
4. Data invullen en blokken genereren: het JavaScript (JS) ontvangt het gestructureerde JSON-object, normaliseert het en koppelt de velden aan native Gutenberg-blokken.
Hieronder de logica achter elke fase.
1. Een custom API-endpoint registreren
De eerste stap in de AI Content Builder-plugin is het registreren van een API-endpoint. Dat is essentieel, omdat het AI-model seconden tot zelfs minuten bezig kan zijn met het verwerken van de audio en het genereren van een antwoord. Met een REST-endpoint verstuur je asynchrone verzoeken vanuit de bedieningselementen in de zijbalk, zodat de interface niet blokkeert.
Een custom API-endpoint laat je bovendien veilige AI-calls doen zonder inloggegevens bloot te geven, via het ingebouwde authenticatiesysteem van WordPress.
De logica voor het registreren en initialiseren van het endpoint staat in het PHP-bestand van de plugin, in de klassemethoden init() en register_rest_routes().
public static function init(): void {
// Register the custom REST endpoint used by the sidebar JS.
add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
...
}
Door de aanroep aan de hook rest_api_init te koppelen, registreert de plugin de route pas wanneer er een REST API-verzoek binnenkomt. Dat scheelt onnodige vertraging bij het laden van pagina’s.
Routes configureer je met de methode register_rest_routes(), zoals in de code hieronder:
public static function register_rest_routes(): void {
register_rest_route(
self::REST_NAMESPACE,
self::REST_ROUTE,
array(
'methods' => WP_REST_Server::CREATABLE, // Alias for POST.
'callback' => array( __CLASS__, 'handle_generate_request' ),
'permission_callback' => static function (): bool {
// Reject unauthenticated or insufficiently privileged requests early.
return current_user_can( 'edit_posts' );
},
'args' => array(
'audio_id' => array(
'type' => 'integer',
'required' => true,
),
),
)
);
}
Wat deze methode doet:
- De functie
register_rest_route()heeft drie parameters: de namespace van de route, de route zelf en een configuratie-array. WP_REST_Server::CREATABLEis een alias voor de POST-methode en zorgt voor maximale compatibiliteit met de interne architectuur van WordPress.permission_callbackis een anonieme functie die de toegang beperkt tot ingelogde gebruikers die hun eigen artikelen mogen aanmaken en bewerken. Bij ongeautoriseerde toegang blokkeert WordPress het verzoek vóór verwerking en geeft het automatisch een 401 Unauthorized– of 403 Forbidden-fout terug.argsis een optionele array met extra parameters waarmee je het API-antwoord bijstuurt. Je geeft er onder meer mee aan welke data het verzoek aan het endpoint moet teruggeven.audio_idis een array met parameters die het vereiste datatype vastlegt. Is de waarde geen geheel getal of ontbreekt hij, dan stopt de REST API de uitvoering met een foutmelding.
Tot slot moet de zijbalk van de editor weten waar de data naartoe gaat. Daarvoor gebruik je de functie wp_localize_script() binnen de methode enqueue_editor_assets().
public static function enqueue_editor_assets(): void {
...
wp_localize_script(
'ai-content-builder-editor',
'AICBData',
array(
'restPath' => '/' . self::REST_NAMESPACE . self::REST_ROUTE,
'nonce' => wp_create_nonce( 'wp_rest' ),
)
);
}
- De functie
wp_localize_script()koppelt normaal gesproken data aan een geregistreerd script voor een JavaScript-variabele. Hier gebruiken we hem om data van PHP naar JavaScript door te geven via het globale objectAICBData. restPathis het adres van het endpoint. Door het hier op te geven, hoef je het niet hardcoded in je JavaScript-bestand te zetten.noncestelt een beveiligingstoken in om ongeautoriseerde toegang te voorkomen.
2. Via de AI Client tekst uit een audiobestand halen
Het hart van de plugin is de methode handle_generate_request(). Die voert een reeks taken uit, van beveiligingscontroles tot het genereren van de artikelcontent die in de blokeditor wordt geplaatst.
Eerst controleert de methode of de AI Client beschikbaar is en of AI-ondersteuning niet is uitgeschakeld op de site.
public static function handle_generate_request( WP_REST_Request $request ) {
if ( ! function_exists( 'wp_ai_client_prompt' ) ) {
return new WP_Error(
'ai_client_unavailable',
'WordPress AI Client is not available. This plugin requires WordPress 7.0+.',
array( 'status' => 500 )
);
}
if ( function_exists( 'wp_supports_ai' ) && ! wp_supports_ai() ) {
return new WP_Error(
'ai_disabled',
'AI support is disabled on this site.',
array( 'status' => 403 )
);
}
...
}
Gaat er iets mis, dan geven de controles respectievelijk een 500 of een 403 terug.
Het volgende codeblok doet dit:
- haalt de ID van het audiobestand uit het verzoek
- controleert of die ID een positief geheel getal is
- controleert het bestandstype
- haalt het MIME-type op
- leest de bestandsinhoud en codeert die in Base64
$audio_id = absint( $request->get_param( 'audio_id' ) );
if ( ! $audio_id ) {
return new WP_Error( 'invalid_audio_id', 'Invalid audio ID.', array( 'status' => 400 ) );
}
$attachment = get_post( $audio_id );
if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
return new WP_Error( 'audio_not_found', 'Audio attachment not found.', array( 'status' => 404 ) );
}
$mime_type = (string) get_post_mime_type( $audio_id );
if ( 0 !== strpos( $mime_type, 'audio/' ) ) {
return new WP_Error( 'invalid_audio_type', 'Attachment must be an audio file.', array( 'status' => 400 ) );
}
$audio_path = get_attached_file( $audio_id );
if ( ! $audio_path || ! file_exists( $audio_path ) ) {
return new WP_Error( 'audio_path_missing', 'Audio file path not found on server.', array( 'status' => 404 ) );
}
$audio_bytes = file_get_contents( $audio_path );
if ( false === $audio_bytes ) {
return new WP_Error( 'audio_read_failed', 'Unable to read audio file.', array( 'status' => 500 ) );
}
$audio_base64 = base64_encode( $audio_bytes );

Het binaire bestand is nu een string die je naar de AI Client kunt sturen. Tijd om de tekst eruit te halen:
$output_language = self::get_output_language();
$transcription_builder = wp_ai_client_prompt(
"Transcribe this voice note accurately into $output_language. Return plain text only."
)
->with_file( $audio_base64, $mime_type )
->using_temperature( 0.1 );
if ( ! $transcription_builder->is_supported_for_text_generation() ) {
return new WP_Error(
'no_supported_model',
'No configured AI model can process this request. Configure a provider in Settings > Connectors.',
array( 'status' => 400 )
);
}
$transcript = $transcription_builder->generate_text();
Wat de code hierboven doet:
get_output_language()is een statische methode die elders in het script is gedefinieerd en de locale van de site teruggeeft. (Zie GitHub.)wp_ai_client_prompt()initialiseert een nieuw verzoek met de hoofdprompt.with_file()geeft de AI Client door dat we een multimodaal verzoek sturen en accepteert de bestandsinhoud in Base64 plus het MIME-type.using_temperature()bepaalt hoe deterministisch het antwoord is. We zetten de waarde laag voor een getrouwe transcriptie van de audio.- De methode
is_supported_for_text_generation()controleert of de AI-provider tekst kan genereren op basis van de aangeleverde data. Ondersteunt de provider geen multimodale invoer, dan stopt de plugin met een foutmelding. - De methode
generate_text()start het HTTP-verzoek.
3. De audiotranscriptie omzetten naar gestructureerde content
Met het transcript in handen gaat de plugin opnieuw naar de AI-provider, nu voor een gestructureerd JSON-antwoord. Daarvoor definiëren we eerst een array die het JSON-formaat beschrijft.
$schema = array(
'type' => 'object',
'properties' => array(
'title' => array( 'type' => 'string' ),
'sections' => array(
'type' => 'array',
'items' => array(
'type' => 'object',
'properties' => array(
'heading' => array( 'type' => 'string' ),
'level' => array(
'type' => 'integer',
),
'paragraphs' => array(
'type' => 'array',
'items' => array( 'type' => 'string' ),
),
'bullet_points' => array(
'type' => 'array',
'items' => array( 'type' => 'string' ),
),
),
'required' => array( 'heading', 'level', 'paragraphs' ),
),
),
),
'required' => array( 'title', 'sections' ),
);
Met deze structuur geeft de AI een JSON-object terug met een titel en een array met secties. Elke sectie bevat een kop, een kopniveau, minstens één alinea en opsommingstekens.
Nu het schema staat, configureren we het tweede verzoek aan de AI Client:
$structured_json = wp_ai_client_prompt(
"Convert the following transcript into a concise, blog-ready draft in $output_language.\n" .
"Return JSON with a post title and body sections.\n" .
"Each section must have: heading, level (2 or 3), and paragraphs (array).\n" .
"If useful, include bullet_points (array) for short actionable lists.\n" .
"Use short, clear headings and readable paragraph text.\n\n" .
"Transcript:\n" . $transcript
)
->using_system_instruction( "You are a professional WordPress content editor. Always write in $output_language (use appropriate spelling, grammar, and conventions for that language variant)." )
->using_temperature( 0.4 )
->as_json_response( $schema )
->generate_text();
if ( is_wp_error( $structured_json ) ) {
return $structured_json;
}
De belangrijkste punten uit deze code:
using_system_instruction()definieert de persona van het model.using_temperature( 0.4 )zet de temperatuur hoger, waardoor de AI meer creatieve ruimte krijgt en vlottere, rijkere tekst produceert.as_json_response( $schema )laat de client het antwoord in een gestructureerd formaat leveren.- De plugin stopt zodra er een fout optreedt.
De volgende stap is het decoderen en opschonen van de data.
$structured = json_decode( (string) $structured_json, true );
if ( ! is_array( $structured ) ) {
return new WP_Error(
'invalid_ai_json',
'Could not parse structured AI response.',
array( 'status' => 500 )
);
}
$normalized = self::normalize_structured_post( $structured );
if ( '' === $normalized['title'] && empty( $normalized['sections'] ) ) {
return new WP_Error(
'empty_structured_content',
'The AI provider returned empty structured content.',
array( 'status' => 500 )
);
}
In de code hierboven:
- De functie
json_decode()zet de JSON-string om in een associatieve PHP-array. - Klopt de JSON niet, dan geeft de controle daarna een 500-statuscode terug met een duidelijke foutmelding.
- De statische methode
normalize_structured_post()schoont de output van de provider op en normaliseert die, vóórdat hij naar JavaScript gaat (zie de definitie van deze functie op GitHub).
Daarna hoef je de output alleen nog aan JavaScript door te geven om er native Gutenberg-blokken van te maken.
4. Gutenberg-ready output genereren
De volgende stap koppelt de JSON-output aan native Gutenberg-blokken. Dat gebeurt aan de clientkant, in het bestand editor.js.
Selecteert de gebruiker een audiobestand, dan draait deze code:
function AIContentBuilderSidebar() {
const [ audioId, setAudioId ] = useState( 0 );
...
const onSelectAudio = function ( media ) {
if ( ! media || ! media.id ) {
return;
}
setAudioId( media.id );
setAudioLabel( media.title || media.filename || ( 'Audio #' + media.id ) );
setNotice( null );
};
...
}
Die code haalt de ID van het opgeslagen audiobestand uit de WordPress-database.
Klikt de gebruiker op de knop Generate Content, dan stuurt de functie onGenerate() met apiFetch() een POST-verzoek naar het API-endpoint, inclusief de audio-ID.
const onGenerate = async function () {
...
try {
const response = await apiFetch( {
path: AICBData.restPath,
method: 'POST',
headers: {
'X-WP-Nonce': AICBData.nonce,
},
data: {
audio_id: audioId,
},
} );
...
}
...
}
awaitpauzeert de functie, zodat de browser niet blokkeert terwijl je op het antwoord van de AI wacht.- Zodra het antwoord binnen is, komt het JSON-object in de variabele
response.
De variabele response bevat een object met deze structuur:
{
title: "Two Wheels to the Medina: ...",
sections: [
{
heading: "A Well-Deserved Rest in the Red City",
level: 2,
paragraphs: [ "On April 24th, our group of seven motorcyclists..." ],
bullet_points: []
},
{
heading: "Diving into the Medina and Jemaa el-Fnaa",
level: 2,
paragraphs: [ "We spent the day exploring the historic Medina..." ],
bullet_points: [
"Navigating the vibrant, maze-like alleys of the ancient Medina",
"Tasting traditional Berber tagines and Moroccan mint tea",
"Shopping for handmade leather goods, spices, and lanterns in the souks"
]
},
{...}
],
content: "Fallback plain text...",
transcript: "Full transcript..."
}
Dat object bevat alles wat je nodig hebt om de blokken te bouwen. Het script kan alleen zowel een JSON-string als in een object geneste JSON binnenkrijgen. Daarom volgt er eerst een normalisatiestap voordat de data eruit worden gehaald:
const normalizedSections = normalizeSectionsPayload( response.sections );
- De functie
normalizeSectionsPayload()zet een onzekeresectionspayload om in een array. (Zie de code op GitHub.)
Daarna geef je de variabele normalizedSections als argument door aan de functie die de velden uit sections omzet in native Gutenberg-blokken:
const structuredBlocks = buildBlocksFromSections( normalizedSections );
Hieronder een fragment uit de functie buildBlocksFromSections():
function buildBlocksFromSections( sections ) {
if ( ! Array.isArray( sections ) ) {
return [];
}
const blocks = [];
sections.forEach( function ( section ) {
if ( ! section || 'object' !== typeof section ) {
return;
}
const heading =
( 'string' === typeof section.heading )
? section.heading.trim()
: '';
const level = ( 3 === section.level ) ? 3 : 2;
if ( heading ) {
blocks.push(
createBlock( 'core/heading', {
content: heading,
level: level,
} )
);
}
...
} );
return blocks;
}
In de code hierboven doorloopt de forEach() loop de data-array en haalt daar section.heading en section.level uit, zodat de native functie createBlock() ermee aan de slag kan.
Hoe section.paragraphs en section.bullet_points worden gekoppeld, zie je in de broncode op GitHub.
Eindeloze uitbreidingsmogelijkheden
AI in WordPress opent nieuwe mogelijkheden voor sitebeheerders én ontwikkelaars. Waar je vroeger een complete netwerkinfrastructuur vanaf nul opbouwde om AI-features aan je WordPress-site toe te voegen, is het automatiseren van je redactionele workflow nu een stuk eenvoudiger geworden.
De voorbeeldplugin uit het tweede deel van dit artikel laat één use case zien. Maar hij maakt duidelijk hoe je nu tools bouwt die sitebeheer en contentbewerking flink vereenvoudigen. Daarnaast opent deze architectuur de deur naar features die eerder te complex of te duur waren om te bouwen.
En dit is nog maar het begin. AI ontwikkelt zich snel en zal ongetwijfeld een grote golf aan innovatie op gang brengen.
Over innovatie gesproken: heb je de hosting van Kinsta al geprobeerd? Wil je je site draaien op de beste technologie die er vandaag voor WordPress beschikbaar is, probeer Kinsta dan zonder risico of neem contact op met ons salesteam voor meer informatie.