New `registerInserterMediaCategory` API

From WordPress 6.4, extenders can register their own inserter media categories and provide users with more options from which to choose.

Even though the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.’s media categories are a blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor setting, it is a private one, which means it cannot be updated through the public updateSettings action. Extenders can only add new inserter media categories, and they don’t have any control over the core media categories, except for being able to disable the Openverse media categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. with enableOpenverseMediaCategory block editor setting.

Every inserter media category should have a unique name property, which is used internally like an id, so it’s best to prefix this. Additionally, each category should have a unique label to be differentiated from the other ones( property).

You can read more about the used interfaces that a media category, media item and the request for media should abide to, on the documentation pages.

The example uses the Openverse category object and just updates the names used: 'core/block-editor' ).registerInserterMediaCategory( {
	name: 'my-new-category',
	labels: {
		name: 'My new category',
		search_items: 'Search Openverse',
	mediaType: 'image',
	async fetch( query = {} ) {
		const defaultArgs = {
			mature: false,
			excluded_source: 'flickr,inaturalist,wikimedia',
			license: 'pdm,cc0',
		const finalQuery = { ...query, ...defaultArgs };
		// Sometimes you might need to map the supported request params 
                // according to `InserterMediaRequest`.
		// interface. In this example the `search` query param is named `q`.
		const mapFromInserterMediaRequest = {
			per_page: 'page_size',
			search: 'q',
		const url = new URL( '' );
		Object.entries( finalQuery ).forEach( ( [ key, value ] ) => {
			const queryKey = mapFromInserterMediaRequest[ key ] || key;
			url.searchParams.set( queryKey, value );
		} );
		const response = await window.fetch( url, {
			headers: {
				'User-Agent': 'WordPress/inserter-media-fetch',
		} );
		const jsonResponse = await response.json();
		const results = jsonResponse.results;
		return ( result ) => ( {
			// If your response result includes an `id` prop 
                        // that you want to access later, it should
			// be mapped to `InserterMediaItem`'s `sourceId` prop. 
                        // This can be useful if you provide a report URL getter.
			// Additionally you should always clear the `id` value of 
                        // your response results because it is used to identify 
                        // WordPress media items.
			id: undefined,
			caption: result.caption,
			previewUrl: result.thumbnail,
		} ) );
	getReportUrl: ( { sourceId } ) =>
		`${ sourceId }/report/`,
	isExternalResource: true,
} );

Props to @bph and @webcommsat for review.

#6-4, #dev-notes, #dev-notes-6-4