Developers
Filters, hooks and constants for customising Contexta — post types, page builders, audits, the CTR curve, retries, licensing and rate limits.
Developers
Contexta is built to be adjusted without touching plugin files. Everything below is a
standard WordPress filter — put these in your theme's functions.php or a small
site-specific plugin.
Content and post types
rm_supported_post_types
Which post types appear in the editor sidebar.
add_filter( 'rm_supported_post_types', function ( $types ) {
$types[] = 'portfolio';
return $types;
} );
rm_editorial_post_types
Which post types are treated as editorial content (articles) rather than products, affecting how prompts are built.
the_content
Standard WordPress. Contexta's front-end CTA output respects it.
Internal links
rm_internal_links_limit
Maximum number of link suggestions returned per article.
add_filter( 'rm_internal_links_limit', fn() => 8 );
rm_internal_links_min_score
Minimum relevance score a candidate must reach to be suggested. Raise it for fewer, stronger matches.
rm_slug_stopwords
Words ignored when extracting keywords from titles and slugs. Ships with stopwords for French, English, Arabic, Spanish, German, Portuguese and Dutch — extend it for your language.
add_filter( 'rm_slug_stopwords', function ( $words ) {
return array_merge( $words, [ 'nuovo', 'della' ] );
} );
Commerce
rm_commerce_checks
Which product checks run in the readiness audit.
// Skip the weight check — shipping data lives in another system.
add_filter( 'rm_commerce_checks', function ( $checks ) {
return array_diff( $checks, [ 'weight' ] );
} );
Valid names: image, price, description, short_desc, category, gtin, brand,
weight.
rm_commerce_audit_limit
How many products a single audit pass covers.
rm_commerce_field_threshold
The minimum length before a description counts as thin.
rm_product_sync_config
The post type, meta keys and taxonomy Contexta reads products from. Override this to support a non-WooCommerce shop plugin.
rm_product_sync_limit / rm_product_context_limit
How many products are synced into memory, and how many can be referenced in a single prompt.
AI and prompts
rm_anthropic_api_key
Supply the API key programmatically — useful for storing it in an environment variable instead of the database.
add_filter( 'rm_anthropic_api_key', fn() => getenv( 'ANTHROPIC_API_KEY' ) );
rm_claude_model
Force a model, ignoring the setting.
rm_claude_model_choices
Add or remove models from the Settings dropdown.
rm_memory_char_budget
Character budget for the site-memory context block injected into each prompt.
rm_ai_rate_limit_per_hour
Override the per-user hourly AI action cap.
// Unlimited for administrators, default for everyone else.
add_filter( 'rm_ai_rate_limit_per_hour', function ( $limit ) {
return current_user_can( 'manage_options' ) ? 0 : $limit;
} );
contexta_competitor_ttl_days
How long competitor research stays fresh. Default 30 days.
Search Console import
rm_gsc_header_aliases
Extra column-header names to recognise when parsing a CSV. Contexta already handles many languages; add yours if an export isn't recognised.
add_filter( 'rm_gsc_header_aliases', function ( $aliases ) {
$aliases['clicks'][] = 'klikk';
return $aliases;
} );
AI traffic
rm_ai_referral_rate_limit
How many beacon hits one visitor may send per window. Default 20. Set to 0 to disable
throttling entirely.
add_filter( 'rm_ai_referral_rate_limit', fn() => 50 );
rm_ai_referral_rate_window
The window in seconds. Default 600 (ten minutes).
Indexing
contexta_instant_index_submit
Return false to skip IndexNow submission for a specific URL.
add_filter( 'contexta_instant_index_submit', function ( $submit, $url ) {
return strpos( $url, '/private/' ) === false;
}, 10, 2 );
Language and branding
rm_site_language_name
Override the detected language name sent to the AI.
contexta_plugin_display_name
Rebrand the plugin's display name in the admin. The product name is deliberately not translatable — this filter is the supported way to change it.
Page builders
Contexta reads a page's text, images and links from the builder that stores them, so audits
are correct on sites where post_content is empty.
rm_builder_signatures
The meta-key patterns used to recognise a builder's stored data. Add your own builder here
and every check — thin content, alt text, internal links, llms.txt, commerce — picks it up
at once.
add_filter( 'rm_builder_signatures', function ( $sigs ) {
$sigs['my_builder'] = [ '_my_builder_data' ];
return $sigs;
} );
rm_builder_min_words
How many words post_content must hold before Contexta trusts it and skips the builder
lookup. Default 20.
Writing back to a page builder
Contexta edits builder pages one text field at a time. Which fields it is willing to touch is a list, not a guess — a wrong guess would overwrite a layout setting rather than a sentence, so an unrecognised widget is skipped and simply not offered.
rm_elementor_text_keys
Elementor settings keys that hold editable prose, by widget type. Add your own widget here and it becomes editable in Contexta.
add_filter( 'rm_elementor_text_keys', function ( $keys ) {
$keys['my-widget'] = [ 'headline', 'body' ];
return $keys;
} );
rm_shortcode_text_fields
The same idea for the shortcode builders. inner means the text between the tags and may
hold HTML; anything else names an attribute, which is plain text only.
add_filter( 'rm_shortcode_text_fields', function ( $fields ) {
$fields['my_module'] = [ 'inner', 'subtitle' ];
return $fields;
} );
rm_shortcode_builders
Which detected builders are edited through the shortcode path. Defaults to Divi and WPBakery.
rm_builder_is_writable
Final say on whether a page's body text can be written back where the reader will see it.
Return true for a builder you have taught Contexta to write, and the editor swaps its
warning for the block panel.
add_filter( 'rm_builder_is_writable', function ( $writable, $builder, $post_id ) {
return $builder === 'My Builder' ? true : $writable;
}, 10, 3 );
rm_builder_signatures
Documented under Page builders — this is what makes a builder readable. Writing needs one of the filters above as well.
Extending the admin
The Pro add-on drives the base plugin entirely through these, so anything Pro can add to the editor, another plugin can add the same way.
rm_editor_config (filter)
The configuration array handed to the editor's JavaScript. Add your own keys.
add_filter( 'rm_editor_config', function ( array $cfg ) {
$cfg['myFeature'] = true;
return $cfg;
} );
rm_editor_scripts_enqueued (action)
Fires after the editor's scripts are registered. Hang your own script off rm-editor here
so the dependency resolves.
rm_admin_scripts_enqueued (action)
Fires on every Contexta admin screen, passed the page slug (rm-map, rm-editor, …).
contexta_settings_tabs (filter)
The Settings tabs, as [ slug, icon, label ] rows. Receives the tabs and whether the
licence is valid.
contexta_editor_tabs · contexta_editor_seo_panel · contexta_editor_content_panel · contexta_sidebar_actions (actions)
Render points inside the editor: the tab strip, the two panels, and the sidebar's action area.
contexta_is_pro · contexta_pro_url (filters)
The Pro capability seam. contexta_is_pro decides whether Pro features are unlocked;
contexta_pro_url is where an upgrade link points.
Search Console import
rm_gsc_file_names
The file names shown on the import screen. Search Console names the files in the account's own language, so these are translatable and default to the English ones.
add_filter( 'rm_gsc_file_names', function ( $names ) {
$names['dates'] = 'Graphique.csv';
return $names;
} );
contexta_llms_txt_descriptions
Supply the one-line descriptions used in llms.txt yourself, skipping the AI call. Return
an array keyed by URL, or null to let Contexta decide — which means an AI description with
Pro, and a trimmed excerpt without it.
add_filter( 'contexta_llms_txt_descriptions', function ( $descriptions, $items ) {
return array_map( fn( $i ) => my_summary( $i['url'] ), $items );
}, 10, 2 );
rm_memory_has_catalog
Whether this site has a product catalogue. Returning false hides the site-memory product
layer entirely; returning true shows it for a shop Contexta did not detect on its own.
Scoring and the CTR curve
rm_ctr_curve
Expected click-through rate by position, used for every lost-clicks estimate. Replace it with your own industry's curve if you have measured one.
add_filter( 'rm_ctr_curve', function ( $curve ) {
$curve[1] = 0.32;
return $curve;
} );
rm_ctr_curve_floor
The floor applied past the end of the curve, so a very deep page never scores zero or
negative. Default 0.0005.
rm_chars_per_word_dense · rm_chars_per_word_sea
Characters per word when counting text in scripts that do not space their words — Han and kana (default 2), and Thai, Lao, Khmer and Myanmar (default 5). Only affects word-count estimates such as thin-content detection.
Audits
rm_audit_max_posts · rm_audit_limits
How many posts the content audit sweeps, and the length thresholds it judges titles and descriptions by.
rm_speed_max_pages · rm_speed_page_choices · rm_speed_per_page
The default number of pages the speed audit fetches, the choices offered in the selector, and the per-page time budget.
rm_speed_lcp_min_bytes · rm_speed_limits
When the main image counts as heavy, and the thresholds for JavaScript weight and render-blocking file counts.
rm_answers_max_pages · rm_answers_content_types
How many pages answer readiness checks, and which post types it treats as answerable content.
rm_answers_stale_days
How old a page must be before Updated recently fails. Default suits evergreen content; lower it for news.
rm_answers_lead_min_chars · rm_answers_lead_max_chars · rm_answers_question_marks
What counts as a quotable opening, and how many question-form headings a page needs.
rm_hreflang_multilingual · rm_hreflang_sample
Whether the site is treated as multilingual (auto-detected from your translation plugin), and how many pages the hreflang check samples.
rm_decay_min_position_drop · rm_decay_min_click_drop · rm_decay_min_impressions
How far a page must fall between imports before Losing ground reports it.
rm_ai_nojs_pages · rm_ai_nojs_pass_words · rm_ai_nojs_fail_words
Which pages the no-JavaScript check samples and the word counts that decide a pass.
Reliability
rm_claude_attempts
How many times a Claude request is attempted when Anthropic answers busy or rate limited. Default 3. A refusal such as an invalid key is never retried.
add_filter( 'rm_claude_attempts', fn() => 5 );
rm_claude_retry_wait
Seconds to wait before a retry. Anthropic's Retry-After header takes precedence when
present.
rm_claude_effort
The effort level for a single request, before it is sent. Receives the computed level, the
request's max_tokens, and the chosen mode. Return low, medium, high, xhigh, max,
or an empty string to send nothing (which the API treats as high).
add_filter( 'rm_claude_effort', function ( $level, $max, $mode ) {
return $max > 4000 ? 'xhigh' : $level;
}, 10, 3 );
rm_effort_short_task_tokens
The max_tokens value at or below which a request counts as a short task in Balanced mode.
Default 800.
rm_effort_models
Which model IDs accept output_config.effort. An ID that is not listed has the field
omitted, so add a newly released model here to opt it in before Contexta ships an update.
rm_model_prices
Per-model USD rates per million tokens, used for the cost readout.
add_filter( 'rm_model_prices', function ( $rates ) {
$rates['claude-opus-6'] = [ 'input' => 5.0, 'output' => 25.0 ];
return $rates;
} );
rm_batch_claim_timeout
How long a batch item stays claimed by a browser before it is released back to the queue. Default 10 minutes — this is what stops a closed tab from stalling a run.
rm_license_grace
How long a licence that verified recently keeps working while the licence server cannot be reached. Default 3 days. A genuine refusal ignores this.
add_filter( 'rm_license_grace', fn() => WEEK_IN_SECONDS );
rm_index_daily_limit
Daily URL-inspection budget before Contexta stops and tells you the quota is reached.
Licensing
contexta_license_api
Point the licence client at a different API base. Mostly useful for staging.
add_filter( 'contexta_license_api', fn() => 'https://staging-api.example.com' );
Constants
| Constant | Purpose |
|---|---|
RM_VER | Plugin version |
RM_DIR / RM_URL | Plugin path and URL |
RM_BRAND | Product name |
RM_PRODUCT_SLUG | Product slug used with the licence server |
RM_LICENSE_API | Optional override of the licence API base |
Third-party integrations
Contexta detects and works with these automatically — no configuration:
- SEO plugins — Yoast SEO, Rank Math, All in One SEO, SEOPress, The SEO Framework, Slim SEO
- WPML — translations are detected, and Google submission can cover every language version
- WooCommerce — product catalogue for memory, CTAs and the commerce audit
- WordPress 7.0 Connectors — a site-wide Anthropic key
Data storage
Everything lives in your own database: options prefixed rm_, post meta prefixed _rm_,
and transients prefixed rm_. uninstall.php removes all of it when the plugin is deleted
through WordPress.