Skip to content

Hooks & filters ​

Checks and scanning ​

HookTypeParametersPurpose
lumtera_rule_classesfilterstring[] $classesClass names of the checks to load. Add or remove checks. See Custom checks.
lumtera_register_rulesactionRuleRegistry $rulesRegister check instances with $rules->register(). The same ID replaces a check.
lumtera_post_scannedactionint $post_id, Report $report, array|null $previousAfter a post is checked and its results stored: on save, after an Elementor save, after a dismissal, in Check all content, the REST scan route, wp lumtera scan, the check-post ability and Pro's re-checks after an ignore rule changes. $previous is the previous summary, or null on the first check.
lumtera_bulk_batch_doneactionbool $doneAfter each batch of Check all content, and once at the end of wp lumtera scan. $done is true when the whole run has finished.
lumtera_pre_render_contentfilterstring|null $html, string $content, int $post_idReturn HTML to check instead of rendering the post content. Only runs for saved posts. Lumtera's own page builder integrations (Elementor, Divi, Beaver Builder, Bricks, Oxygen, WPBakery) use it. The HTML you return is used as-is.
lumtera_rendered_contentfilterstring $html, int $post_idChange the rendered HTML before it's checked. $post_id is 0 for unsaved content. Lumtera's Advanced Custom Fields and WooCommerce integrations use it to add field values and the product short description.
lumtera_max_check_bytesfilterint $bytes (default 524288)The largest content accepted for a live check. At least 1024.
lumtera_check_rate_limitfilterint $limit (default 120)Live checks per user per minute. 0 turns the limit off.
lumtera_readability_languagefilterstring $lang, int $post_idTwo-letter language code used to pick the reading-level formula. Default: the post's language in Polylang or WPML, otherwise the site language. $post_id is 0 when unknown.
lumtera_readability_supportedfilterbool $supported, string $langWhether to measure a reading level. Default: true for en, es, fr, de, it and nl. Forcing it on for another language uses the English formula.
lumtera_link_to_document_messagefilterstring $message, string $href, string $extMessage for the link-to-document check
lumtera_new_window_phrasesfilterstring[] $phrasesLowercase phrases that count as warning that a link opens a new tab, for the link-new-window check

Example: check a custom field ​

Add a custom field's HTML to what Lumtera checks:

php
add_filter( 'lumtera_rendered_content', function ( string $html, int $post_id ): string {
	if ( $post_id && 'event' === get_post_type( $post_id ) ) {
		$html .= wp_kses_post( get_post_meta( $post_id, 'event_details', true ) );
	}
	return $html;
}, 10, 2 );

Advanced Custom Fields values are added already. You only need this for other fields.

Example: accept a phrase in another language ​

php
add_filter( 'lumtera_new_window_phrases', function ( array $phrases ): array {
	$phrases[] = 'nueva pestaña';
	return $phrases;
} );

Example: react to new errors ​

php
add_action( 'lumtera_post_scanned', function ( int $post_id, $report, ?array $previous ) {
	$errors = $report->to_array()['counts']['error'];
	if ( $errors > ( $previous['errors'] ?? 0 ) ) {
		// Errors went up on this save.
	}
}, 10, 3 );

Dismissing and ignoring ​

HookTypeParametersPurpose
lumtera_issue_dismissedactionint $post_id, string $fingerprint, string $rule_id, string $noteAfter an issue is dismissed on a post
lumtera_issue_restoredactionint $post_id, string $fingerprint, string $rule_idAfter a dismissed issue is restored
lumtera_ignored_issuefilterarray|null $record, Issue $issue, int $post_idHide a finding wherever it appears, not just on one post. Return null to leave it open, or a record to report it as dismissed. $post_id is 0 for a whole page.

A record returned from lumtera_ignored_issue can have these keys:

KeyTypeMeaning
reasonstringWhy it's ignored. Shown as the dismissal note.
userintWho ignored it
timeintWhen, as a Unix time
sourcestringWhere the record comes from. Default global.
severitystringOptional. The most severe finding it may hide: a record with warning never hides an error.
can_restoreboolOptional. Whether the current user may undo it.
restore_pathstringOptional. A REST path that undoes it with DELETE.
expiresintOptional. When it stops applying, 0 for never.

Ignored findings aren't stored as open issues, so they don't count in scores or reports. Lumtera Pro's ignore rules use this filter, and leave a record another plugin already returned unchanged.

php
// Hide the vague "Read more" links a theme prints on every archive card.
add_filter( 'lumtera_ignored_issue', function ( $record, \Lumtera\Issue $issue ) {
	if ( null === $record && 'link-ambiguous-text' === $issue->rule_id
		&& str_contains( $issue->context, 'class="card__more"' ) ) {
		return [ 'reason' => 'The card heading gives the link context.', 'severity' => 'warning' ];
	}
	return $record;
}, 10, 2 );

Manual checks ​

HookTypeParametersPurpose
lumtera_manual_test_savedactionint $post_id, string $test, array|null $recordAfter a manual check result is recorded or cleared. $test is an ID such as keyboard. $record is null when cleared, otherwise { result, note, failed, user, time }.

Permissions ​

HookTypeDefaultControls
lumtera_capabilityfilterlumtera_view_reportsOverview, Content, Free vs Pro, the Dashboard widget, Check all content, /site-summary, the site-summary ability, and Pro's report screens and routes (page checks, documents, reports, the conformance report, creating tracker issues)
lumtera_dismiss_errors_capabilityfilterlumtera_dismiss_errorsDismissing and restoring errors, and (Pro) closing an error task as Won't fix
lumtera_review_capabilityfilterlumtera_review_modeReview mode on the front end, on top of edit_post for the post
lumtera_images_capabilityfilterupload_filesOpening the alt text manager. Editing an image still needs edit_post on it.

The three lumtera_* capabilities are given to roles under Settings → Permissions. By default, roles that can edit others' posts get lumtera_view_reports and lumtera_dismiss_errors, and roles that can edit posts get lumtera_review_mode. Administrators always have all three. A filter wins over the settings. See Roles & permissions.

Changing settings, including check severities, always needs manage_options.

php
// Let site managers with a custom capability see the reports.
add_filter( 'lumtera_capability', fn() => 'manage_accessibility' );

Admin screens ​

HookTypeParametersPurpose
lumtera_edit_urlfilterstring $url, int $post_idThe "edit" link Lumtera uses everywhere. Point it at your page builder.
lumtera_screen_orderfilterstring[] $orderOrder of Lumtera's screens (page slugs), for tabs and the submenu
lumtera_admin_tabsfilterarray $tabs (slug => label)Tabs in the Lumtera header. Add your own screen.
lumtera_admin_tab_badgesfilterarray $badges (slug => tag)Short badges shown after tab labels
lumtera_settings_sectionsfilterarray $sections (slug => label)Settings sections. Built in: general, checks, ai, permissions and email-summary.
lumtera_settings_section_{$slug}actionRenders your own settings section
lumtera_overview_after_statsactionarray $totalsOutput below the Overview summary cards
lumtera_content_actionsactionarray $filtersButtons in the Content report header
lumtera_selectable_post_typesfilterWP_Post_Type[] $typesContent types offered under Settings → Content to check
lumtera_pricing_urlfilterstring $urlWhere "Buy Pro" links go
lumtera_show_upgradefilterbool $showWhether "Upgrade to Pro" buttons show
lumtera_elementor_preview_assetsactionRuns when Elementor's preview loads its styles

Media Library ​

HookTypeParametersPurpose
lumtera_import_embedded_altfilterbool $importWhether Lumtera copies alt text embedded in an uploaded image's metadata (IPTC) into the Media Library, when the image has none. Default: true only before WordPress 7.0, which does this itself.

Email summary ​

HookTypeParametersPurpose
lumtera_email_summary_activefilterbool $activeWhether the weekly email summary is scheduled and sent. Default: the setting, and always off while Lumtera Pro is active (Pro has its own weekly summary).

AI ​

HookTypeParametersPurpose
lumtera_ai_alt_text_prefilterarray|WP_Error|null $pre, int $image_id, array $contextReturn alt text suggestions to skip the WordPress AI Client, for example to use another service. Return null to carry on.
lumtera_ai_link_text_prefilterarray|WP_Error|null $pre, array $context, int $post_idThe same, for link text suggestions
lumtera_ai_headings_prefilterarray|WP_Error|null $pre, array $context, int $post_idThe same, for heading suggestions
lumtera_ai_summary_prefilterarray|WP_Error|null $pre, array $context, int $post_idThe same, for plain-language summaries
lumtera_ai_rate_limitfilterint $limit (default 30)AI requests one user may make in 10 minutes, across all AI features. 0 turns the limit off.

For alt text, $context has post_title, caption, heading, nearby, linked and link_text. Return the same shape the AI Client call produces:

php
add_filter( 'lumtera_ai_alt_text_pre', function ( $pre, int $image_id, array $context ) {
	$suggestion = my_captioning_service( wp_get_attachment_url( $image_id ), $context );

	return [
		'suggestions' => [ $suggestion ],
		'decorative'  => false,
		'note'        => '',
	];
}, 10, 3 );

The writing filters get what would be sent to the provider, and your answer is tidied the same way as the provider's:

Filter$context keysReturn
lumtera_ai_link_text_prelink_text, destination, destination_title, sentence, paragraph, post_title, rule{ suggestions: string[], note }
lumtera_ai_headings_premode (bold or outline), post_title; for bold: text, next, previous; for outline: paragraphsbold: { suggestions: string[], note }. outline: { headings: [ { before, text } ], note }, where before is the 1-based paragraph number.
lumtera_ai_summary_prepost_title, text, words, target{ summary, note }

Return a WP_Error to fail the request with your own message.

Site fixes ​

HookTypeParametersPurpose
lumtera_site_fixes_skip_link_targetfilterstring $targetSkip-link target ID (without #) when none is saved
lumtera_site_fixes_theme_has_skip_linkfilterbool $hasWhether the theme already prints a skip link, so Lumtera adds none
lumtera_site_fixes_viewportfilterstring $contentThe viewport tag content printed by the zoom fix. Default: width=device-width, initial-scale=1.
lumtera_site_fixes_filter_contentfilterbool $runWhether the link fixes run on this request
php
// My theme prints its skip link in a way Lumtera can't detect.
add_filter( 'lumtera_site_fixes_theme_has_skip_link', '__return_true' );

JavaScript hooks ​

These use wp.hooks in the block editor. Load your script with lumtera-editor as a dependency.

HookTypeSignaturePurpose
lumtera.quickFixersfilter( fixers ) => fixersQuick fixes, keyed by check ID. Each is ( block, issue ) => { label, done, apply } | null. See Add a quick fix.
lumtera.issueActionsfilter( actions, issue, { postId, recheck } ) => actionsExtra buttons on each issue card. Return an array of elements. recheck() runs the check again, for example after your action changed what's reported. Lumtera's AI writing suggestions and Pro's Track fix and Ignore everywhere… buttons use it.
lumtera.readingActionsfilter( actions, readability, { postId, builder } ) => actionsExtra elements under the reading level. readability is the report's readability object. builder is true when a page builder renders the post. Lumtera's AI summary uses it.
js
wp.hooks.addFilter( 'lumtera.issueActions', 'acme/report', ( actions, issue ) => [
	...actions,
	wp.element.createElement( wp.components.Button, {
		variant: 'link',
		onClick: () => window.open( 'https://example.com/ask?rule=' + issue.rule ),
	}, 'Ask the team' ),
] );

The block editor data store lumtera/checks exposes the current results. Selectors: getReport(), getCounts(), getStatus(), getError(), getCheckedAt(), isHighlighting() and getBlockSeverity( clientId ).

js
const counts = wp.data.select( 'lumtera/checks' ).getCounts();

Lumtera Pro Pro ​

HookTypeParametersPurpose
lumtera_pro_canfilterbool $allowed, string $feature, int $planPlan gating for white_label, acr and portfolio. Only reached when the license is active.
lumtera_pro_license_is_activefilterbool $active, string $statusMaster switch for Pro features. On a network, a license below the Agency plan is already false here for sites other than the main site.
lumtera_pro_network_licensefilterbool $networkWhether the license is stored network-wide
lumtera_pro_use_action_schedulerfilterbool $use (default true)Use Action Scheduler when it's loaded (for example with WooCommerce), instead of WP-Cron
lumtera_pro_send_alertfilterbool $send, int $post_id, Issue[] $newStop an alert about new errors on a post. $new is keyed by fingerprint.
lumtera_pro_send_page_alertfilterbool $send, string $url, string[] $newStop an alert from a scheduled page check. $new holds the new errors' fingerprints.
lumtera_pro_importingfilterbool $importingTreat this request as an import: record the starting point without alerting. Pro turns it on while it re-checks posts after an ignore rule changes.
lumtera_pro_scheduled_templatesfilterarray $templates (each {url, title})Templates that scheduled checks find automatically
lumtera_pro_scheduled_urlsfilterarray $urls (each {url, title})The final list of pages for scheduled checks (same-site only, up to 25)
lumtera_pro_portfolio_safe_httpfilterbool $safe (default true)Use WordPress's safe HTTP client for portfolio connections. Turn off only for local development.
lumtera_pro_eventactionstring $event, array $payloadFires for every Pro event. See the event list.
lumtera_pro_event_payloadfilterarray $payloadChange an event payload before it's logged and sent
lumtera_pro_reports_sectionsactionOutput below the report list on the Reports screen. Pro's conformance report card uses it.
php
// Don't alert about posts in the "Archive" category.
add_filter( 'lumtera_pro_send_alert', function ( bool $send, int $post_id ) {
	return $send && ! has_category( 'archive', $post_id );
}, 10, 2 );

// Always check the pricing page on schedule.
add_filter( 'lumtera_pro_scheduled_urls', function ( array $urls ) {
	array_unshift( $urls, [ 'url' => home_url( '/pricing/' ), 'title' => 'Pricing' ] );
	return $urls;
} );

// Forward every Pro event to your own logger.
add_action( 'lumtera_pro_event', function ( string $event, array $payload ) {
	error_log( $event . ' ' . wp_json_encode( $payload['object'] ) );
}, 10, 2 );

Constants Pro ​

Set these in wp-config.php:

ConstantEffect
LUMTERA_PRO_ENCRYPTION_KEYKey used to encrypt portfolio passwords, webhook secrets and issue tracker tokens. Set it if your salts change, for example when a host rotates them.
LUMTERA_PRO_DELETE_REPORTStrue deletes reports, fix history, page results and the activity log on uninstall
LUMTERA_PRO_DELETE_LICENSEtrue deletes the license on uninstall