### PHP Type Hinting Example Source: https://github.com/elightup/slim-seo/blob/master/AGENTS.md Demonstrates the use of type hints for function parameters and return types in PHP. ```php public function get_posts( array $args = [] ): array { // ... } ``` -------------------------------- ### PHP Class Structure Example Source: https://github.com/elightup/slim-seo/blob/master/AGENTS.md Illustrates the basic structure of a PHP class within the Slim SEO plugin, including namespace, setup method for hooks, and other methods. ```php [ 'meta_title', 'meta_description', 'meta_robots', 'open_graph', 'twitter_cards', 'canonical_url', 'rel_links', 'sitemaps', 'images_alt', 'breadcrumbs', 'feed', 'schema', 'redirection', // 'no_category_base', // opt-in // 'link_attributes', // opt-in ], // ── Code injection ─────────────────────────────────────────────────────── 'header_code' => '', 'body_code' => '', 'footer_code' => '', // ── Social ─────────────────────────────────────────────────────────────── 'facebook_app_id' => '1234567890', 'twitter_site' => '@MySiteHandle', 'default_facebook_image' => 'https://example.com/og-default.jpg', 'default_twitter_image' => 'https://example.com/twitter-default.jpg', // ── AI provider ────────────────────────────────────────────────────────── 'ai_provider' => 'openai', // openai | anthropic | google | openrouter 'ai_model' => 'gpt-4.1-mini', 'ai_api_key' => 'sk-…', // ── Per-content-type meta tag templates ────────────────────────────────── 'home' => [ 'title' => '{{ site.title }} {{ sep }} {{ site.description }}', 'description' => '{{ site.description }}', 'facebook_image' => '', 'twitter_image' => '', 'noindex' => false, ], 'post' => [ 'title' => '{{ post.title }} {{ sep }} {{ site.title }}', 'description' => '{{ post.auto_description }}', 'facebook_image' => '', 'twitter_image' => '', 'noindex' => false, ], 'page' => [ 'title' => '{{ post.title }} {{ sep }} {{ site.title }}', 'description' => '{{ post.auto_description }}', 'noindex' => false, ], 'category' => [ 'title' => '{{ term.name }} {{ sep }} {{ site.title }}', 'description' => '{{ term.auto_description }}', 'noindex' => false, ], // ── Redirection settings ────────────────────────────────────────────────── 'redirection' => [ 'auto_redirection' => true, 'redirect_www' => '', // '' | 'www-to-non' | 'non-to-www' 'force_trailing_slash' => false, 'enable_404_logs' => true, 'auto_delete_404_logs' => 30, // days; -1 = never 'disable_for_single_posts' => false, ], // ── Robots.txt ──────────────────────────────────────────────────────────── 'robots_txt' => "User-agent: *\nDisallow: /wp-admin/\nAllow: /wp-admin/admin-ajax.php\n\nSitemap: https://example.com/sitemap.xml\n", ] ); ``` -------------------------------- ### List 404 Log Entries via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to list 404 log entries from the Slim SEO REST API, with options for pagination. ```bash curl -s \ -H "X-WP-Nonce: " \ "https://example.com/wp-json/slim-seo/404-logs?per_page=50&page=1" ``` -------------------------------- ### Configure Meta Title Templates and Overrides Source: https://context7.com/elightup/slim-seo/llms.txt This example demonstrates how to configure meta title templates for different content types and how to override them programmatically for specific posts or post types. It also shows how to retrieve the rendered title for a given post. ```php // Default templates (set in Settings → Meta Tags): // Home: {{ site.title }} {{ sep }} {{ site.description }} // Post: {{ post.title }} {{ sep }} {{ page }} {{ sep }} {{ site.title }} // Post archive: {{ post_type.labels.plural }} {{ sep }} {{ page }} {{ sep }} {{ site.title }} // Term: {{ term.name }} {{ sep }} {{ page }} {{ sep }} {{ site.title }} // Author: {{ author.display_name }} {{ sep }} {{ page }} {{ sep }} {{ site.title }} // Override a post's title programmatically add_filter( 'slim_seo_meta_title', function ( string $title ) : string { if ( is_singular( 'product' ) ) { $product = wc_get_product( get_the_ID() ); return $product->get_name() . ' — Buy now at ' . get_bloginfo( 'name' ); } return $title; } ); // Per-post meta stored under key 'slim_seo': update_post_meta( 42, 'slim_seo', [ 'title' => 'Custom Title for Post 42', 'description' => 'A hand-written description that overrides auto-generation.', 'noindex' => false, ] ); // Read rendered title for a specific post (respects template + overrides): $title_service = $container->get_service( 'meta_title' ); $rendered = $title_service->get_rendered_singular_value( 42 ); // → "Custom Title for Post 42" ``` -------------------------------- ### Bulk Delete All 404 Logs via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to delete all 404 log entries via the Slim SEO REST API. Requires a nonce. ```bash curl -s -X DELETE \ -H "X-WP-Nonce: " \ https://example.com/wp-json/slim-seo/404-logs ``` -------------------------------- ### PHP Filter for AI Model Selection Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md Example of how to use the `slim_seo_ai_model` filter to programmatically override the selected AI model based on the provider. This allows for custom model forcing. ```php add_filter( 'slim_seo_ai_model', function( $model, $provider ) { if ( $provider === 'openai' ) { return 'gpt-4o'; // Force GPT-4o for OpenAI } return $model; }, 10, 2 ); ``` -------------------------------- ### Create a New Redirect via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to create a new redirect rule via the Slim SEO REST API. Requires a nonce and JSON payload. ```bash curl -s -X POST \ -H "X-WP-Nonce: " \ -H "Content-Type: application/json" \ -d '{"from_url":"/old-page/","to":"/new-page/","type":301,"condition":"exact","enable":1}' \ https://example.com/wp-json/slim-seo/redirects ``` -------------------------------- ### Get Rendered Term Meta Description Source: https://context7.com/elightup/slim-seo/llms.txt Retrieve the rendered meta description for a specific taxonomy term. This is useful for displaying or logging the description that Slim SEO would output. ```php $desc_service = $container->get_service( 'meta_description' ); $rendered = $desc_service->get_rendered_term_value( 15 ); // term_id = 15 // → "Truncated term description, max 160 chars…" ``` -------------------------------- ### Generate Meta Title via OpenAI REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to generate a meta title using the AI Meta Generation REST API with OpenAI. Requires a nonce and JSON payload. ```bash curl -s -X POST \ -H "X-WP-Nonce: " \ -H "Content-Type: application/json" \ -d '{ "type": "title", "title": "10 Tips for Faster WordPress Sites", "content": "WordPress performance is crucial for SEO…", "object": {"ID": 42, "post_type": "post"} }' \ https://example.com/wp-json/slim-seo/meta-tags/ai ``` -------------------------------- ### Initialize Slim SEO and Register Services Source: https://context7.com/elightup/slim-seo/llms.txt This code snippet shows the basic startup process for the Slim SEO plugin, including defining constants, including the autoloader, instantiating the container, registering services, and hooking into WordPress initialization. It also demonstrates how developers can customize behavior by disabling services or retrieving service instances. ```php define( 'SLIM_SEO_VER', '4.9.6' ); define( 'SLIM_SEO_DIR', plugin_dir_path( __FILE__ ) ); define( 'SLIM_SEO_URL', plugin_dir_url( __FILE__ ) ); define( 'SLIM_SEO_REDIRECTS', 'ss_redirects' ); require SLIM_SEO_DIR . 'vendor/autoload.php'; $container = new SlimSEO\Container(); $container->register_services(); // Hook fires at priority 5, before WordPress core sitemaps at priority 10 add_action( 'init', [ $container, 'init' ], 5 ); // ── Developer customization ────────────────────────────────────────────────── // Disable a specific service before it initialises add_action( 'slim_seo_init', function ( SlimSEO\Container $c ) { $c->disable( 'schema' ); // turn off JSON-LD output $c->disable( 'no_category_base' ); // keep /category/ in URLs } ); // Retrieve a live service instance for programmatic use add_action( 'init', function () use ( $container ) { $breadcrumbs = $container->get_service( 'breadcrumbs' ); // $breadcrumbs is a fully-initialised SlimSEO\Breadcrumbs instance } ); // Delete all plugin data when uninstalling (opt-in) define( 'SLIM_SEO_DELETE_DATA', true ); ``` -------------------------------- ### Restrict Sitemap Post Query Source: https://context7.com/elightup/slim-seo/llms.txt Modify the query arguments for post types in the sitemap, for example, to only include visible products. ```php // Restrict posts query (e.g., only show products that are "visible") add_filter( 'slim_seo_sitemap_post_type_query_args', function ( array $args, string $post_type ) : array { if ( $post_type === 'product' ) { $args['tax_query'] = [ [ 'taxonomy' => 'product_visibility', 'field' => 'name', 'terms' => [ 'exclude-from-catalog' ], 'operator' => 'NOT IN', ] ]; } return $args; }, 10, 2 ); ``` -------------------------------- ### Build Assets Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Build frontend assets using npm. Confirm that the build process completes successfully. ```bash npm run build ``` -------------------------------- ### PHP Build Commands for Slim SEO Source: https://github.com/elightup/slim-seo/blob/master/AGENTS.md Commands for linting, auto-fixing, and static analysis of PHP code using Composer. ```bash composer phpcs src ``` ```bash composer phpcbf src ``` ```bash composer phpstan src ``` ```bash composer phpcs path/to/file.php ``` ```bash composer phpstan analyse path/to/file.php ``` -------------------------------- ### Override Twitter Image at Runtime Source: https://context7.com/elightup/slim-seo/llms.txt Dynamically set the Twitter image based on post type, for example, using a video thumbnail for 'video' post types. ```php // Override the Twitter image at runtime add_filter( 'slim_seo_twitter_card_image', function ( string $image ) : string { if ( is_singular( 'video' ) ) { return get_post_meta( get_the_ID(), '_video_thumbnail', true ); } return $image; } ); ``` -------------------------------- ### Run Static Analysis Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Perform static analysis using PHPStan on the AI provider and AI core files. Verify that no critical errors are found. ```bash composer phpstan analyse src/MetaTags/AiProviders/ src/MetaTags/AI.php ``` -------------------------------- ### Add Migration to Upgrade.php Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Introduces a new upgrade method to migrate existing 'openai_key' to the new 'ai_api_key' format and sets default values for 'ai_provider' and 'ai_model' if they don't exist. ```php private function upgrade_to_v2(): void { $option = get_option( 'slim_seo' ) ?: []; // If old openai_key exists and new ai_api_key doesn't if ( ! empty( $option['openai_key'] ) && empty( $option['ai_api_key'] ) ) { $option['ai_api_key'] = $option['openai_key']; $option['ai_provider'] = 'openai'; $option['ai_model'] = 'gpt-4.1-mini'; update_option( 'slim_seo', $option ); } } ``` -------------------------------- ### Delete Redirect via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to delete a specific redirect rule (by ID) via the Slim SEO REST API. Requires a nonce. ```bash curl -s -X DELETE \ -H "X-WP-Nonce: " \ https://example.com/wp-json/slim-seo/redirects/5 ``` -------------------------------- ### Add Custom Schema Entity with Slim SEO Source: https://context7.com/elightup/slim-seo/llms.txt Use the 'slim_seo_schema_graph' filter to add custom entities or modify the entire Schema.org graph. This example adds a 'FAQPage' entity. ```php add_filter( 'slim_seo_schema_graph', function ( array $graph ) : array { $graph[] = [ '@type' => 'FAQPage', 'mainEntity' => [ [ '@type' => 'Question', 'name' => 'What is Slim SEO?', 'acceptedAnswer' => [ '@type' => 'Answer', 'text' => 'A fast, automated SEO plugin for WordPress.', ], ], ], ]; return $graph; } ); ``` -------------------------------- ### List Available AI Models for a Provider Source: https://context7.com/elightup/slim-seo/llms.txt Query the API to see which AI models are available for a specified provider. This is useful for selecting the correct model for AI generation tasks. ```bash curl -s \ -H "X-WP-Nonce: " \ "https://example.com/wp-json/slim-seo/ai/models?provider=openai" ``` -------------------------------- ### Configure 404 Logging and Redirection Settings Source: https://context7.com/elightup/slim-seo/llms.txt Updates the plugin's options to enable 404 logging, configure auto-deletion of logs, and set redirection behaviors. ```php update_option( 'slim_seo', array_merge( get_option( 'slim_seo', [] ), [ 'redirection' => [ 'enable_404_logs' => true, 'auto_delete_404_logs' => 30, // delete logs older than 30 days; -1 = never 'auto_redirection' => true, // auto-redirect changed slugs 'redirect_www' => 'www-to-non', // or 'non-to-www' or '' 'force_trailing_slash' => false, 'disable_for_single_posts' => false, ], ] ) ); ``` -------------------------------- ### Modify Resolved Breadcrumb Links with Slim SEO Filter Source: https://context7.com/elightup/slim-seo/llms.txt Alter the array of breadcrumb links after they have been resolved but before rendering, using the 'slim_seo_breadcrumbs_links' filter. This example inserts a custom 'Shop' crumb. ```php add_filter( 'slim_seo_breadcrumbs_links', function ( array $links ) : array { // Insert a custom crumb between Home and the rest array_splice( $links, 1, 0, [ [ 'text' => 'Shop', 'url' => home_url( '/shop/' ), ] ] ); return $links; } ); ``` -------------------------------- ### AI Class request() Method Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md Handles AI requests by dynamically selecting and instantiating a provider based on settings. Validates API keys and models, and makes the remote post request. ```php private function request( string $prompt, string $content ): array { $settings = get_option( 'slim_seo' ) ?: []; $provider = $settings['ai_provider'] ?? 'openai'; $model = $settings['ai_model'] ?? ''; $api_key = $settings['ai_api_key'] ?? ''; if ( empty( $api_key ) ) { return $this->response( __( 'Please provide an API key in settings.', 'slim-seo' ) ); } // Get provider instance $provider_class = $this->get_provider_class( $provider ); if ( ! $provider_class ) { return $this->response( __( 'Invalid provider selected.', 'slim-seo' ) ); } $provider = new $provider_class(); // Validate model - use default if empty if ( empty( $model ) ) { $models = $provider->get_models(); $model = $models[0]['value'] ?? ''; } if ( empty( $model ) ) { return $this->response( __( 'No models available for the selected provider.', 'slim-seo' ) ); } // Build request $url = $provider->get_api_url(); $headers = $provider->get_headers( $api_key ); $body = $provider->build_request_body( $prompt, $content, $model ); // Make request $response = wp_safe_remote_post( $url, [ 'headers' => $headers, 'body' => wp_json_encode( $body ), 'timeout' => 45, ] ); // Handle response... return $this->handle_response( $response, $provider ); } private function get_provider_class( string $provider ): ?string { $providers = [ 'openai' => OpenAI::class, 'google' => Google::class, 'anthropic' => Anthropic::class, 'openrouter'=> OpenRouter::class, ]; return $providers[ $provider ] ?? null; } ``` -------------------------------- ### Update Redirect via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to update an existing redirect rule (by ID) via the Slim SEO REST API. Requires a nonce and JSON payload. ```bash curl -s -X PUT \ -H "X-WP-Nonce: " \ -H "Content-Type: application/json" \ -d '{"to":"/updated-destination/","type":302}' \ https://example.com/wp-json/slim-seo/redirects/5 ``` -------------------------------- ### Implement OpenAI Provider in PHP Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Provides the implementation for the OpenAI AI provider. This class adheres to the ProviderInterface, defining specific methods for interacting with the OpenAI API. ```php 'application/json', 'Authorization' => "Bearer $api_key", ]; } public function build_request_body( string $prompt, string $content, string $model ): array { return [ 'model' => $model, 'temperature' => 0.5, 'input' => [ [ 'role' => 'system', 'content' => $prompt, ], [ 'role' => 'user', 'content' => $content, ], ], ]; } public function parse_response( array $response ): string { return $response['output'][0]['content'][0]['text'] ?? ''; } public function get_models(): array { return [ [ 'value' => 'gpt-4.1-mini', 'label' => 'GPT-4.1 Mini' ], [ 'value' => 'gpt-4.1', 'label' => 'GPT-4.1' ], [ 'value' => 'gpt-4o-mini', 'label' => 'GPT-4o Mini' ], [ 'value' => 'gpt-4o', 'label' => 'GPT-4o' ], ]; } } ``` -------------------------------- ### Override Indexing Decision Based on Post Age Source: https://context7.com/elightup/slim-seo/llms.txt Conditionally control the 'index' directive for posts based on their age using the `slim_seo_robots_index` filter. This example noindexes posts older than two years. ```php add_filter( 'slim_seo_robots_index', function ( bool $indexed, int $object_id ) : bool { // Noindex anything older than 2 years $post = get_post( $object_id ); if ( $post && strtotime( $post->post_date ) < strtotime( '-2 years' ) ) { return false; } return $indexed; }, 10, 2 ); ``` -------------------------------- ### Force Noindex on Author Archive Pages Source: https://context7.com/elightup/slim-seo/llms.txt Apply a 'noindex' directive to all author archive pages using the `wp_robots` filter. This example also demonstrates removing other robot directives like `max-snippet` and `max-video-preview`. ```php add_filter( 'wp_robots', function ( array $robots ) : array { if ( is_author() ) { $robots['noindex'] = true; unset( $robots['max-snippet'], $robots['max-video-preview'] ); } return $robots; } ); ``` -------------------------------- ### Trigger Batch Migration Programmatically Source: https://context7.com/elightup/slim-seo/llms.txt Initiate a batch migration of posts programmatically. This action hook is typically handled internally by the SlimSEO Migration class and processes posts in batches. ```php /* Supported source plugins: - Yoast SEO (rank_math_title → slim_seo[title], etc.) - Rank Math - All in One SEO (AIOSEO) - The SEO Framework - SEOPress - Squirrly SEO - Redirection plugin (redirect rules only) - Simple 301 Redirects (redirect rules only) */ // ── Migration AJAX flow (called sequentially from JS) ──────────────────────── /* wp_ajax_ss_prepare_migration → verify source plugin is active wp_ajax_ss_reset_counter → reset session counter to 0 wp_ajax_ss_migrate_posts → batch-migrate 10 posts at a time wp_ajax_ss_migrate_terms → batch-migrate 10 terms at a time wp_ajax_ss_migrate_redirects → import all redirect rules at once wp_ajax_ss_migrate_robots → copy robots.txt content */ // Trigger a batch migration programmatically (usually done via the UI): add_action( 'wp_ajax_ss_migrate_posts', function () { // Handled internally by SlimSEO\Migration\Migration // Each call processes 10 posts and returns JSON progress } ); // Field mapping example (Rank Math → Slim SEO): /* rank_math_title → slim_seo[title] rank_math_description → slim_seo[description] rank_math_canonical_url → slim_seo[canonical] rank_math_robots → slim_seo[noindex] (noindex in array → true) rank_math_facebook_image_url → slim_seo[facebook_image] rank_math_twitter_image_url → slim_seo[twitter_image] */ ``` -------------------------------- ### Bulk AI Generation - Process Posts Source: https://context7.com/elightup/slim-seo/llms.txt Initiate bulk AI generation for post titles and/or descriptions. This endpoint processes posts in chunks, advancing by a specified offset. Use `skip_title` and `skip_description` to control which meta tags are generated. ```bash curl -s -X POST \ -H "X-WP-Nonce: " \ -H "Content-Type: application/json" \ -d '{ "phase": "posts", "offset": 0, "post_types": ["post","page","product"], "skip_title": true, "skip_description": false }' \ https://example.com/wp-json/slim-seo/bulk-ai/chunk ``` -------------------------------- ### Migrate AI Settings Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md Migrates existing 'openai_key' to 'ai_api_key' and sets default AI provider and model if not already present. This function should be called on plugin upgrade. ```php public function migrate_ai_settings(): void { $settings = get_option( 'slim_seo' ) ?: []; // If old openai_key exists and new ai_api_key doesn't if ( ! empty( $settings['openai_key'] ) && empty( $settings['ai_api_key'] ) ) { $settings['ai_api_key'] = $settings['openai_key']; $settings['ai_provider'] = 'openai'; $settings['ai_model'] = 'gpt-4.1-mini'; update_option( 'slim_seo', $settings ); } } ``` -------------------------------- ### Delete Single 404 Log Entry via REST API Source: https://context7.com/elightup/slim-seo/llms.txt Example using cURL to delete a specific 404 log entry (by ID) via the Slim SEO REST API. Requires a nonce. ```bash curl -s -X DELETE \ -H "X-WP-Nonce: " \ https://example.com/wp-json/slim-seo/404-logs/123 ``` -------------------------------- ### Backend Settings: AI Provider and Model Dropdowns Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md HTML snippets for the AI provider and model selection dropdowns, and the shared API key input in the backend settings. The model dropdown is intended to be populated by JavaScript. ```html ``` -------------------------------- ### OpenAI Provider Implementation Details Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md Details for the OpenAI AI provider, including API URL, required headers, request body format, and response parsing logic. Note that the request format is a JSON object with model, temperature, and input array. ```json { "model": "gpt-4.1-mini", "temperature": 0.5, "input": [ { "role": "system", "content": "{prompt}" }, { "role": "user", "content": "{content}" } ] } ``` -------------------------------- ### Backend Settings: Stored AI Options Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md PHP code showing how AI provider, model, and API key settings are sanitized and stored. Includes logic for migrating existing OpenAI API keys. ```php $option['ai_provider'] = sanitize_text_field( $option['ai_provider'] ?? 'openai' ); $option['ai_model'] = sanitize_text_field( $option['ai_model'] ?? '' ); $option['ai_api_key'] = sanitize_text_field( $option['ai_api_key'] ?? '' ); ``` -------------------------------- ### Bulk AI Generation - Process Terms Source: https://context7.com/elightup/slim-seo/llms.txt Initiate bulk AI generation for term titles and/or descriptions. Similar to post processing, this operates in chunks and allows skipping title or description generation. ```bash curl -s -X POST \ -H "X-WP-Nonce: " \ -H "Content-Type: application/json" \ -d '{ "phase": "terms", "offset": 0, "taxonomies": ["category","product_cat"], "skip_title": false, "skip_description": false }' \ https://example.com/wp-json/slim-seo/bulk-ai/chunk ``` -------------------------------- ### List Available AI Models Source: https://context7.com/elightup/slim-seo/llms.txt Retrieve a list of available AI models for a specified provider. This is useful for understanding which AI models you can utilize for meta generation. ```APIDOC ## List Available AI Models ### Description This endpoint lists the available AI models for a given AI provider. This helps in selecting the appropriate model for AI-driven SEO tasks. ### Method GET ### Endpoint `/wp-json/slim-seo/ai/models` ### Parameters #### Query Parameters - **provider** (string) - Required - The AI provider (e.g., "openai"). ### Response Example (Response structure not provided in source) ``` -------------------------------- ### Set Twitter Site Handle Source: https://context7.com/elightup/slim-seo/llms.txt Configure the Twitter site handle, which can also be set in the plugin's settings. ```php // Set Twitter site handle (also configurable in Settings → Social) add_filter( 'slim_seo_twitter_card_site', function () : string { return '@MySiteHandle'; } ); ``` -------------------------------- ### JavaScript for AI Provider/Model Behavior Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md This script handles the dynamic population of AI model dropdowns based on the selected AI provider. It maps providers to their available models and updates the model selection accordingly. Ensure the HTML elements with IDs 'ss-ai-provider' and 'ss-ai-model' exist. ```javascript (function () { 'use strict'; const providerSelect = document.getElementById('ss-ai-provider'); const modelSelect = document.getElementById('ss-ai-model'); if (!providerSelect || !modelSelect) { return; } const providerModels = { openai: [ { value: 'gpt-4.1-mini', label: 'GPT-4.1 Mini' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, { value: 'gpt-4o-mini', label: 'GPT-4o Mini' }, { value: 'gpt-4o', label: 'GPT-4o' }, ], google: [ { value: 'gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash (Experimental)' }, { value: 'gemini-2.0-flash', label: 'Gemini 2.0 Flash' }, { value: 'gemini-1.5-flash-8b', label: 'Gemini 1.5 Flash 8B' }, { value: 'gemini-1.5-flash', label: 'Gemini 1.5 Flash' }, ], anthropic: [ { value: 'claude-sonnet-4-20250514', label: 'Claude Sonnet 4 (Latest)' }, { value: 'claude-3-5-sonnet-20240620', label: 'Claude 3.5 Sonnet' }, { value: 'claude-3-5-haiku-20240620', label: 'Claude 3.5 Haiku' }, ], openrouter: [ { value: 'openai/gpt-4.1-mini', label: 'GPT-4.1 Mini' }, { value: 'openai/gpt-4o-mini', label: 'GPT-4o Mini' }, { value: 'anthropic/claude-3.5-sonnet-20240620', label: 'Claude 3.5 Sonnet' }, { value: 'google/gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash' }, { value: 'meta/llama-3.3-70b-instruct', label: 'Llama 3.3 70B' }, ], }; function populateModels(provider) { const models = providerModels[provider] || []; const currentValue = modelSelect.value; modelSelect.innerHTML = ''; if (models.length === 0) { const option = document.createElement('option'); option.value = ''; option.textContent = 'Select a provider first'; modelSelect.appendChild(option); return; } models.forEach(model => { const option = document.createElement('option'); option.value = model.value; option.textContent = model.label; modelSelect.appendChild(option); }); // Try to preserve selection if it exists in new provider const matchingOption = Array.from(modelSelect.options).find(opt => opt.value === currentValue); if (matchingOption) { modelSelect.value = currentValue; } } // Populate on page load const initialProvider = providerSelect.value || 'openai'; populateModels(initialProvider); if (modelSelect.value) { modelSelect.value = ''; } // Handle provider change providerSelect.addEventListener('change', function () { populateModels(this.value); }); })(); ``` ```javascript (function () { 'use strict'; const providerSelect = document.getElementById('ss-ai-provider'); const modelSelect = document.getElementById('ss-ai-model'); if (!providerSelect || !modelSelect) { return; } const providerModels = { openai: [ { value: 'gpt-4.1-mini', label: 'GPT-4.1 Mini' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, { value: 'gpt-4o-mini', label: 'GPT-4o Mini' }, { value: 'gpt-4o', label: 'GPT-4o' }, ], google: [ { value: 'gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash (Experimental)' }, { value: 'gemini-2.0-flash', label: 'Gemini 2.0 Flash' }, { value: 'gemini-1.5-flash-8b', label: 'Gemini 1.5 Flash 8B' }, { value: 'gemini-1.5-flash', label: 'Gemini 1.5 Flash' }, ], anthropic: [ { value: 'claude-sonnet-4-20250514', label: 'Claude Sonnet 4 (Latest)' }, { value: 'claude-3-5-sonnet-20240620', label: 'Claude 3.5 Sonnet' }, { value: 'claude-3-5-haiku-20240620', label: 'Claude 3.5 Haiku' }, ], openrouter: [ { value: 'openai/gpt-4.1-mini', label: 'GPT-4.1 Mini' }, { value: 'openai/gpt-4o-mini', label: 'GPT-4o Mini' }, { value: 'anthropic/claude-3.5-sonnet-20240620', label: 'Claude 3.5 Sonnet' }, { value: 'google/gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash' }, { value: 'meta/llama-3.3-70b-instruct', label: 'Llama 3.3 70B' }, ], }; function populateModels(provider) { const models = providerModels[provider] || []; const currentValue = modelSelect.value; modelSelect.innerHTML = ''; if (models.length === 0) { const option = document.createElement('option'); option.value = ''; option.textContent = 'Select a provider first'; modelSelect.appendChild(option); return; } models.forEach(model => { const option = document.createElement('option'); option.value = model.value; option.textContent = model.label; modelSelect.appendChild(option); }); // Try to preserve selection if it exists in new provider const matchingOption = Array.from(modelSelect.options).find(opt => opt.value === currentValue); if (matchingOption) { modelSelect.value = currentValue; } } // Populate on page load const initialProvider = providerSelect.value || 'openai'; populateModels(initialProvider); if (modelSelect.value) { modelSelect.value = ''; } // Handle provider change providerSelect.addEventListener('change', function () { populateModels(this.value); }); })(); ``` -------------------------------- ### Slim SEO Directory Structure Source: https://github.com/elightup/slim-seo/blob/master/AGENTS.md Overview of the directory structure for the Slim SEO plugin, showing the organization of core, helpers, meta tags, schema, sitemaps, migration, and integrations. ```text src/ ├── Core.php # Main plugin class ├── Helpers/ # Helper classes ├── MetaTags/ # Meta tags generation ├── Schema/ # Schema.org structured data ├── Sitemaps/ # XML sitemaps ├── Migration/ # Data migration from other plugins └── Integrations/ # Third-party plugin integrations ``` -------------------------------- ### Update AI Integration UI in tools.php Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Replaces the existing OpenAI Integration section with a new UI for selecting AI providers, models, and entering API keys. Includes options for OpenAI, Google, Anthropic, and OpenRouter. ```php

Get API keys.', 'slim-seo' ), 'https://slimseo/docs/ai-settings/' ) ); ?>

``` -------------------------------- ### Enable Author Sitemap Source: https://context7.com/elightup/slim-seo/llms.txt Enable the generation of an XML sitemap for authors/users, which is disabled by default. ```php // Enable author/user sitemap (disabled by default) add_filter( 'slim_seo_sitemap_users', '__return_true' ); ``` -------------------------------- ### Add Defaults in Settings.php Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Adds default values for the new AI integration fields ('ai_provider', 'ai_model', 'ai_api_key') to the defaults array in Settings.php. This ensures these fields are always present. ```php private $defaults = [ // ... existing ... 'ai_provider' => 'openai', 'ai_model' => 'gpt-4.1-mini', 'ai_api_key' => '', ]; ``` -------------------------------- ### Run PHP Linting Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Execute PHP CodeSniffer to check for coding standard violations in specified files. Ensure no errors are reported. ```bash composer phpcs src/MetaTags/AiProviders/ src/MetaTags/AI.php src/Settings/Settings.php src/Settings/MetaTags/RestApi.php src/Upgrade.php src/Settings/tabs/tools.php ``` -------------------------------- ### Update Webpack Configuration Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Add a new entry point to your webpack configuration file to include the AI settings script. ```javascript entry: { // ... existing ... 'settings-ai': './js/settings-ai.js', }, ``` -------------------------------- ### Multilingual Support (WPML & Polylang) Hreflang Output Source: https://context7.com/elightup/slim-seo/llms.txt Demonstrates the expected `hreflang` alternate link output in sitemaps when using WPML or Polylang. This ensures proper SEO for multilingual websites. ```php /* When WPML is active: - sitemap.xml includes for every translated version of each URL - Adds x-default hreflang pointing to the default language - Settings strings are registered for translation via WPML String Translation - The redirection home URL is filtered to respect WPML's active language When Polylang is active: - Same sitemap hreflang behaviour - Language switcher on the settings page */ // The integrations activate automatically — no code is needed. // To verify WPML hreflang output, check any post sitemap: // curl https://example.com/sitemap-post-type-post.xml | grep 'hreflang' /* */ ``` -------------------------------- ### AI Meta Description Generation Logic Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/plans/2026-03-23-ai-multi-provider-implementation.md Handles the regeneration of meta descriptions using AI. It constructs a prompt, appends content, and optionally includes rewrite rules and previous values before making a request to the AI service. ```php public function regenerate( string $content, ?string $previous_value = null ): array { $prompt = "Strict rules:\n - Do NOT use emojis - Do NOT use quotation marks - Do NOT add information not present in the content - Avoid keyword stuffing or unnatural repetition Output rules: - Return ONLY the meta description text - No explanations, no extra lines PROMPT; $content = "Content:\n{$content}"; // Regenerate (rewrite) logic if ( $previous_value ) { $prompt .= "\n\n" . $this->get_rewrite_rule(); $content .= "\n\nPrevious meta description:\n{$previous_value}"; } return $this->request( $prompt, $content ); } ``` -------------------------------- ### OpenRouter Provider Implementation Details Source: https://github.com/elightup/slim-seo/blob/master/docs/superpowers/specs/2026-03-23-ai-multi-provider-design.md Details for the OpenRouter AI provider, noting that it uses the same API URL structure, headers, request format, and response parsing as OpenAI. ```text - API URL: https://openrouter.ai/api/v1/responses - Headers: Authorization: Bearer {api_key} - Request format: Same as OpenAI - Response parse: Same as OpenAI - Note: OpenRouter uses same Responses API format as OpenAI ``` -------------------------------- ### Configure AI Provider and Model via Plugin Settings Source: https://context7.com/elightup/slim-seo/llms.txt Set the default AI provider, model, and API key within the WordPress plugin settings. This configuration applies globally unless overridden. ```php update_option( 'slim_seo', array_merge( get_option( 'slim_seo', [] ), [ 'ai_provider' => 'anthropic', // openai | anthropic | google | openrouter 'ai_model' => 'claude-opus-4-5', 'ai_api_key' => 'sk-ant-…', ] ) ); ```