> */ public static function all(): array { $content = array( 'onboarding' => array( 'title' => __( 'Quick-start wizard', 'acez-seo' ), 'description' => __( 'A few questions about your site let you set sensible defaults right away (Organization, post author, LocalBusiness, AI provider, preparing for AI bots, Google Search Console verification) instead of starting from scratch. Every step and the whole wizard can be skipped — nothing gets locked, and you can finish the configuration manually in the other tabs.', 'acez-seo' ), 'example' => '', ), 'setup_health' => array( 'title' => __( 'Setup health', 'acez-seo' ), 'description' => __( 'Shows how many of the basic setup steps (Organization, AI Assistant, AI-era SEO, Visibility & GSC) are already configured — based on the actual state of your settings, not whether you ran the Wizard. Manual configuration in the other tabs counts the same way.', 'acez-seo' ), 'example' => '', ), 'seo_title' => array( 'title' => __( 'SEO title', 'acez-seo' ), 'description' => __( 'The title shown in search results and the browser tab. Leave blank to use the default template for this content type.', 'acez-seo' ), 'example' => '%post_title% %sep% %site_name%', ), 'seo_description' => array( 'title' => __( 'Meta description', 'acez-seo' ), 'description' => __( 'A short description shown below the title in search results. 120–155 characters recommended — Google usually truncates longer text.', 'acez-seo' ), 'example' => '%post_excerpt%', ), 'seo_canonical' => array( 'title' => __( 'Canonical URL', 'acez-seo' ), 'description' => __( 'Tells search engines which URL is the "original" for this content — important when the same content is available at multiple URLs (e.g. with and without parameters). Leave blank to use the post\'s default URL.', 'acez-seo' ), 'example' => __( 'https://yourdomain.com/example-page/', 'acez-seo' ), ), 'seo_robots' => array( 'title' => __( 'Index / Follow', 'acez-seo' ), 'description' => __( '"Index" lets search engines add this page to their results. "Follow" lets them follow links on this page. Turn off "Index" for pages you don\'t want in Google (e.g. drafts, thank-you pages).', 'acez-seo' ), 'example' => '', ), 'seo_sitemap_exclude' => array( 'title' => __( 'Exclude from the sitemap', 'acez-seo' ), 'description' => __( 'Removes this content from the sitemap (wp-sitemap.xml) submitted to search engines — independent of the "Index" setting. This is NOT the same as noindex: a page can stay indexable (e.g. linked from a menu) while being deliberately omitted from the sitemap (e.g. a thin/duplicate page you don\'t want to prioritize for sitemap-driven crawling). Content marked "noindex" is excluded from the sitemap automatically, without this toggle.', 'acez-seo' ), 'example' => '', ), 'seo_llms_exclude' => array( 'title' => __( 'Exclude from llms.txt', 'acez-seo' ), 'description' => __( 'Skips this content when building llms.txt — independent of the "Index" setting. This is NOT the same as noindex: a page can stay indexable while being deliberately omitted from the AI-model guide (e.g. a legal/admin page you don\'t want suggested as "important" content). Content marked "noindex" (including by another active SEO plugin) is skipped automatically, without this toggle.', 'acez-seo' ), 'example' => '', ), 'schema_graph' => array( 'title' => __( 'Schema.org / JSON-LD graph', 'acez-seo' ), 'description' => __( 'Structured data helps search engines and AI bots understand the content (type, author, date, etc.) and can enable so-called rich results. The plugin generates this automatically; here you can add your own extra nodes or fully override the generated graph. You can use shortcodes in property values — their output is inserted as plain text (no HTML) and cached for up to an hour.', 'acez-seo' ), 'example' => '{"@type":"FAQPage","mainEntity":[...]}', ), 'schema_types' => array( 'title' => __( 'Generating schema.org', 'acez-seo' ), 'description' => __( 'When enabled, this content type automatically gets the appropriate schema.org node (e.g. Article for posts). You can disable this if another plugin already handles it.', 'acez-seo' ), 'example' => '', ), 'schema_type_override' => array( 'title' => __( 'Forcing the schema type', 'acez-seo' ), 'description' => __( 'Automatic detection only sees the WordPress content type (post → Article, everything else → WebPage) — it cannot know what a builder actually renders. If you e.g. built a blog page using a Divi/Elementor module, pick “Blog” here; and if the plugin should not declare a main node for this post at all, pick “None”. Forcing only changes the declaration made to search engines (the main node\'s type); the page content and the remaining nodes (Organization, FAQ, custom ones) stay untouched, and the node\'s properties are still filled in automatically from the post\'s data.', 'acez-seo' ), 'example' => '', ), 'organization' => array( 'title' => __( 'Organization / WebSite', 'acez-seo' ), 'description' => __( 'Your organization\'s data (name, logo, social profiles) used in the Organization and WebSite nodes of the generated graph — these build your brand\'s "identity" in the eyes of search engines.', 'acez-seo' ), 'example' => '', ), 'location_rules' => array( 'title' => __( 'Location rules', 'acez-seo' ), 'description' => __( 'Restricts meta tag/schema generation to only selected page templates or conditions (e.g. only the front page). Leave everything unchecked to apply to all entries of this type.', 'acez-seo' ), 'example' => '', ), 'ai_providers' => array( 'title' => __( 'AI Providers', 'acez-seo' ), 'description' => __( 'Connect an Anthropic, OpenAI, Google Gemini, or OpenRouter account (one key for models from many vendors) to generate titles, SEO descriptions, and image alt text in one click. The API key is encrypted in the database and never displayed again.', 'acez-seo' ), 'example' => '', ), 'ai_model' => array( 'title' => __( 'AI model', 'acez-seo' ), 'description' => __( 'The specific model name for this provider (e.g. a particular Claude, GPT, or Gemini version). Leave blank for the plugin to use a sensible default model — only change this if you need a specific version or a cheaper/faster variant.', 'acez-seo' ), 'example' => '', ), 'organization_logo' => array( 'title' => __( 'Organization logo', 'acez-seo' ), 'description' => __( 'The numeric ID of an image from the Media Library (visible e.g. in the attachment edit URL). The logo goes into the Organization node in schema.org — Google may show it e.g. in the Knowledge Panel. Leave blank to use the site icon (Settings → General).', 'acez-seo' ), 'example' => '', ), 'social_profiles' => array( 'title' => __( 'Social profiles', 'acez-seo' ), 'description' => __( 'Links to your company\'s official profiles (Facebook, X, Instagram, LinkedIn, etc.) go into the "sameAs" property in schema.org — this is how search engines connect your site to those profiles as the same entity.', 'acez-seo' ), 'example' => __( "https://facebook.com/your-page\nhttps://x.com/your-page", 'acez-seo' ), ), 'no_category_base' => array( 'title' => __( 'Removing "/category/" from URLs', 'acez-seo' ), 'description' => __( 'Shortens category URLs, but this changes the URL structure for the whole site — if your category pages are already indexed, search engines need time to re-index the new URLs (old ones redirect automatically, so nothing breaks, but rankings may fluctuate temporarily). Enable this deliberately, ideally on a new site.', 'acez-seo' ), 'example' => '', ), 'author_schema' => array( 'title' => __( 'Author (Person) in schema.org', 'acez-seo' ), 'description' => __( 'Adds a Person node with the post author\'s data (name, profile link) to the schema.org graph. Worth enabling for expert sites/blogs where author credibility matters (Google\'s so-called E-E-A-T) — less relevant for company sites without multiple authors.', 'acez-seo' ), 'example' => '', ), 'local_business' => array( 'title' => __( 'LocalBusiness', 'acez-seo' ), 'description' => __( 'For businesses with a physical location (shop, restaurant, office, practice). Adds an address, phone number, and opening hours to schema.org, helping you appear in local search results and Google Maps. You can find coordinates (latitude/longitude) by right-clicking the location in Google Maps. Skip this section if you operate purely online.', 'acez-seo' ), 'example' => '', ), 'llms_txt' => array( 'title' => __( 'llms.txt — a guide for AI models', 'acez-seo' ), 'description' => __( 'The /llms.txt file (llmstxt.org standard) in markdown format describes the site to language models and points out the most important content — the AI equivalent of a sitemap. Generated automatically with a short description next to each link; posts/pages marked noindex (including noindex set by another active SEO plugin) are skipped. A custom intro lets you add context (what you do, what you recommend). The noai/noimageai signal in meta robots is, in turn, an opt-out of AI training on your content — respected unevenly, but it costs nothing and complements the per-bot blocks from the robots.txt editor. Requires pretty permalinks (like the sitemap).The /llms.txt file (llmstxt.org standard) describes your site to language models in markdown and points at the most important content — a sitemap equivalent for AI. Generated automatically; the custom introduction lets you add context (what you do, what you recommend). The noai/noimageai signal in the robots meta tag, in turn, objects to training models on your content — respected inconsistently, but it costs nothing and complements the per-bot blocks in the robots.txt editor. Requires pretty permalinks (like the sitemap).', 'acez-seo' ), 'example' => '/llms.txt', ), 'llms_footer' => array( 'title' => __( 'llms.txt footer', 'acez-seo' ), 'description' => __( 'Appended at the very end of the generated llms.txt file — a place for a content license, disclaimer, or other fixed closing text.', 'acez-seo' ), 'example' => '', ), 'llms_sitemap_opt_in' => array( 'title' => __( 'Including llms.txt in the sitemap', 'acez-seo' ), 'description' => __( 'By default llms.txt carries a "noindex" header and is not linked from anywhere — it\'s a file for AI bots, not for search results. Enabling this adds /llms.txt as a separate entry to WordPress\'s native sitemap (wp-sitemap.xml) and lifts the noindex header, so search engines CAN index it. If the file contains full post content (not just short descriptions), this risks a duplicate-content issue — enable deliberately.', 'acez-seo' ), 'example' => '', ), 'feature_meta_title' => array( 'title' => __( 'Meta title — the title tag', 'acez-seo' ), 'description' => __( 'Generates the page title tag (what you see on the browser tab and as the result headline in Google) from per-content-type templates and per-post fields. Disable only when another SEO plugin manages titles — two title sources mean duplicate tags.', 'acez-seo' ), 'example' => '', ), 'feature_meta_description' => array( 'title' => __( 'Meta description — the snippet in results', 'acez-seo' ), 'description' => __( 'Generates the meta description shown under the title in search results (custom per post, or from the excerpt/content when empty). A good description improves the click-through rate. Disable if another SEO plugin generates descriptions.', 'acez-seo' ), 'example' => '', ), 'feature_meta_robots' => array( 'title' => __( 'Meta robots — index/follow', 'acez-seo' ), 'description' => __( 'Outputs the robots tag (index/noindex, follow/nofollow) according to per-post and per-content-type settings. When disabled, the plugin stops sending its own directives — only WordPress core and other plugins remain, and your per-post settings stop working.', 'acez-seo' ), 'example' => '', ), 'feature_open_graph' => array( 'title' => __( 'Open Graph — social media sharing', 'acez-seo' ), 'description' => __( 'The og:* tags decide how a link to your site looks when shared on Facebook, LinkedIn or in messengers (title, description, image). Without them the platforms guess — often badly. Disable only if another plugin generates Open Graph.', 'acez-seo' ), 'example' => '', ), 'feature_twitter_cards' => array( 'title' => __( 'Twitter cards — preview on X', 'acez-seo' ), 'description' => __( 'The twitter:* tags control how a link shared on X/Twitter looks (you pick the card type per post: small or with a large image). Disable with another social plugin — duplicate tags get interpreted unpredictably.', 'acez-seo' ), 'example' => '', ), 'feature_canonical' => array( 'title' => __( 'Canonical URL — duplicate-content protection', 'acez-seo' ), 'description' => __( 'Tells search engines the canonical address of a page so variants of the same URL (parameters, comment pagination) do not compete in the index. One of the most important SEO hygiene practices — disable only when another plugin outputs the canonical.', 'acez-seo' ), 'example' => '', ), 'feature_rel_links' => array( 'title' => __( 'rel prev/next links — pagination', 'acez-seo' ), 'description' => __( 'The rel="prev"/"next" links describe page order in paginated archives and multi-page posts. Google has ignored them since 2019, but Bing and other search engines still use them. Enabling costs nothing — disable only if you want absolutely minimal HTML.', 'acez-seo' ), 'example' => '', ), 'feature_sitemap' => array( 'title' => __( 'Sitemap XML — the site map', 'acez-seo' ), 'description' => __( 'WordPress\'s built-in sitemap (/wp-sitemap.xml) helps crawlers find and index all content; the plugin additionally excludes posts marked noindex. Disabling hides the sitemap entirely — do it only if another plugin generates the map.', 'acez-seo' ), 'example' => '', ), 'sitemap_tab' => array( 'title' => __( 'Sitemap tab', 'acez-seo' ), 'description' => __( 'WordPress generates the sitemap itself (/wp-sitemap.xml) — this tab shapes its contents through WordPress\'s official filters, without replacing the sitemap with its own file. The main sitemap switch lives on the Dashboard (the “Sitemap XML” row), and excluding a single post is done in that post\'s SEO meta box.', 'acez-seo' ), 'example' => '', ), 'sitemap_content' => array( 'title' => __( 'Sitemap contents', 'acez-seo' ), 'description' => __( 'Unticked content types and taxonomies disappear from the sitemap entirely. Independently of that, posts marked noindex and manually excluded posts never enter the sitemap — the sitemap always agrees with what you allow to be indexed.', 'acez-seo' ), 'example' => '', ), 'sitemap_users' => array( 'title' => __( 'Author archives in the sitemap', 'acez-seo' ), 'description' => __( 'Author archive pages (e.g. /author/jan/) are often unnecessary in search results on single-author company sites — disabling removes their list from the sitemap. On multi-author blogs they are usually worth keeping.', 'acez-seo' ), 'example' => '', ), 'sitemap_excluded_urls' => array( 'title' => __( 'Excluding URLs from the sitemap', 'acez-seo' ), 'description' => __( 'Typed paths are filtered out of the final sitemap regardless of which section they come from (posts, taxonomies, authors, additional URLs). A path without an asterisk excludes exactly one URL (a trailing slash makes no difference); a trailing asterisk excludes a whole branch. This works alongside — not instead of — the per-post exclusions from the editor.', 'acez-seo' ), 'example' => __( '/promo/*', 'acez-seo' ), ), 'sitemap_custom_urls' => array( 'title' => __( 'Additional URLs in the sitemap', 'acez-seo' ), 'description' => __( 'Pages outside WordPress (e.g. a hand-uploaded HTML file on the same domain) can be added to the sitemap so crawlers are sure to find them. The sitemap standard requires every URL to live on the same domain as the sitemap — URLs from other domains are rejected on save.', 'acez-seo' ), 'example' => __( 'https://yourdomain.com/promo/', 'acez-seo' ), ), 'sitemap_max_urls' => array( 'title' => __( 'URL limit per sitemap page', 'acez-seo' ), 'description' => __( 'WordPress splits the sitemap into pages of 2000 URLs. The value 0 keeps that default limit; lower it only if your server struggles to generate large sitemap pages. The upper bound is 50000 — the maximum for a single sitemap file per Google\'s specification.', 'acez-seo' ), 'example' => '', ), 'feature_image_alt' => array( 'title' => __( 'Image alt texts — automatic fallback', 'acez-seo' ), 'description' => __( 'When an image has no alt text, the plugin fills it in on the fly from the caption or file title — better accessibility and visibility in Google Images. Manually set alt texts are never overwritten; this is only a safety net for empty ones.', 'acez-seo' ), 'example' => '', ), 'feature_rss_backlink' => array( 'title' => __( 'RSS backlink — protecting feed content', 'acez-seo' ), 'description' => __( 'Appends a note "Article X comes from site Y" with a link to the original at the end of posts in the RSS feed. When someone scrapes content from your RSS, the copy carries a link pointing at the source. Disable if the note bothers readers using RSS readers.', 'acez-seo' ), 'example' => '', ), 'feature_schema' => array( 'title' => __( 'Schema.org — the master switch', 'acez-seo' ), 'description' => __( 'The master switch for JSON-LD structured data (Article, WebSite, Organization, FAQ, breadcrumbs, etc.) — this is what enables rich results in Google. Works together with the per-content-type settings: here you turn everything off at once, there selectively. Disable with another schema-generating plugin — duplicate graphs confuse validators.', 'acez-seo' ), 'example' => '', ), 'ai_feature' => array( 'title' => __( 'AI support — what it does and how to activate it', 'acez-seo' ), 'description' => __( 'Enables all AI features of the plugin: the "Generate with AI" buttons for SEO titles and descriptions, product descriptions and schema nodes (FAQ/HowTo) in both editors, plus alt-text generation in the media library. The toggle stays greyed out until AI is ready: go to the AI Providers tab, pick a provider, enter the API key, click "Test connection" and, after a successful test, "Save" — the toggle then unlocks. Generation costs are billed to your account at the provider (limits and counters live in AI Providers → Usage and log).', 'acez-seo' ), 'example' => '', ), 'ai_task_models' => array( 'title' => __( 'Model per task', 'acez-seo' ), 'description' => __( 'Different tasks have different needs: alt texts and meta descriptions are fine with a cheap, fast model, while schema nodes or longer texts come out better with a stronger one. Enter a model identifier valid for the ACTIVE provider (e.g. gpt-4o-mini, claude-opus-4-8, gemini-1.5-flash). Empty field = the model from the provider configuration.', 'acez-seo' ), 'example' => 'gpt-4o-mini', ), 'ai_usage' => array( 'title' => __( 'AI usage and soft limit', 'acez-seo' ), 'description' => __( 'Call counters and approximate tokens (≈4 characters per token, vision counted with a surcharge) are kept locally in your database — nothing is sent externally. The monthly limit is SOFT: once reached, every generation asks for confirmation instead of blocking. The recent-generations log shows the task, model, status and duration — the first place to look when "AI does not work".', 'acez-seo' ), 'example' => '', ), 'ai_schema_nodes' => array( 'title' => __( 'AI-generated schema.org nodes', 'acez-seo' ), 'description' => __( 'The AI proposes a complete FAQPage node (questions and answers based on the post content) or a HowTo node (guide steps). The proposal lands as a new, editable row — nothing is saved automatically; review the questions/steps, adjust them, and only then save the post. Invalid JSON from the AI is rejected before it is added.', 'acez-seo' ), 'example' => '{"@type":"FAQPage","mainEntity":[...]}', ), 'ai_context_schema' => array( 'title' => __( 'Additional instructions for AI (schema)', 'acez-seo' ), 'description' => __( 'Optional text the AI will take into account with PRIORITY when generating the FAQ/HowTo node — e.g. "focus on price and delivery questions" or "keep the steps very short, for beginners". Empty field = generation works as before, based only on the post\'s content.', 'acez-seo' ), 'example' => __( 'focus on price and delivery questions', 'acez-seo' ), ), 'ai_context_keyword' => array( 'title' => __( 'Describe the page topic for AI', 'acez-seo' ), 'description' => __( 'Optional text the AI will take into account with PRIORITY when generating the SEO title, meta description, and keyphrase for this post — e.g. "the phrase must include the city name" or "avoid English words". Empty field = generation works as before, based only on the post\'s content.', 'acez-seo' ), 'example' => __( 'the phrase must include the city name', 'acez-seo' ), ), 'search_intent' => array( 'title' => __( 'Search intent', 'acez-seo' ), 'description' => __( 'We don\'t guess it from the keyword (like some paid tools do) — YOU declare why this content exists, and the AI receives it as extra context when generating the title, description, keyphrase and article. Informational = the reader wants to learn something (educational tone). Navigational = looking for a specific brand/page (emphasize the company name). Commercial = comparing options before buying (emphasize advantages). Transactional = ready to buy/act (action-oriented language). Leave it as "not set" if you don\'t want to change anything — zero effect on generation.', 'acez-seo' ), 'example' => '', ), 'generate_article' => array( 'title' => __( 'Generate article', 'acez-seo' ), 'description' => __( 'The AI writes the full post body (not just meta) in Markdown, which the plugin converts into headings, bold, italics and lists. Two modes: based on what the page already has (title, existing content, meta description), or based on a short description/topic you provide yourself. The generated text lands in a preview — nothing enters the post content until you click "Insert"; if the post already has content, you also choose whether to replace it, append it at the end, or insert at the cursor position.', 'acez-seo' ), 'example' => '', ), 'breadcrumbs' => array( 'title' => __( 'Breadcrumbs', 'acez-seo' ), 'description' => __( 'Insert the [acez_seo_breadcrumbs] shortcode into a post/page (the "Shortcode" block) or into your theme template (echo do_shortcode in PHP) to display a visible breadcrumb trail. The visible trail and the BreadcrumbList node in schema.org use the same data, so they always stay in sync. This toggle controls the shortcode; the graph node is governed by the schema settings.', 'acez-seo' ), 'example' => '[acez_seo_breadcrumbs]', ), 'og_default_image' => array( 'title' => __( 'Default Open Graph image', 'acez-seo' ), 'description' => __( 'The image used when sharing on social media if the post has neither its own OG image nor a featured image. Order: the post\'s OG image → the featured image → this per-content-type default. Recommended size: at least 1200×630 px (~1.91:1 ratio).', 'acez-seo' ), 'example' => '', ), 'og_acf_field' => array( 'title' => __( 'ACF field for the OG image', 'acez-seo' ), 'description' => __( 'Name of an ACF image field whose value will be used as the Open Graph image. Full priority order: the post\'s own OG image → ACF field → featured image → the per-content-type default. Supported field return formats: attachment ID, array and URL. Tip: the %acf:field_name% variable also works in title and description templates for text fields.', 'acez-seo' ), 'example' => 'zdjecie_glowne', ), 'organization_scope' => array( 'title' => __( 'Organization node scope', 'acez-seo' ), 'description' => __( 'By default ("Entire site") the Organization node is the brand identity on every page — the safe standard. Narrowing it (e.g. front page only) is in line with Google\'s guidance for organization markup; on the remaining pages the plugin then also removes the "publisher" references from the WebSite/Article nodes so no dangling references are left. Narrow deliberately — the publisher on Article helps tie content to your brand.', 'acez-seo' ), 'example' => '', ), 'local_business_scope' => array( 'title' => __( 'LocalBusiness node scope', 'acez-seo' ), 'description' => __( 'Google reads LocalBusiness data on pages describing the business — usually the front page and the contact page are enough. "Entire site" emits the node everywhere (harmless, but with no benefit on blog posts); a narrower scope keeps the graph cleaner on the remaining pages.', 'acez-seo' ), 'example' => '', ), 'howto_field' => array( 'title' => __( 'HowTo (step-by-step instructions)', 'acez-seo' ), 'description' => __( 'Enable if this post is a "how to" style guide. Steps are automatically pulled from the first numbered list in the content — nothing needs to be re-typed manually. Google may display such a guide as a rich result with numbered steps directly in search results.', 'acez-seo' ), 'example' => '', ), 'product_fields' => array( 'title' => __( 'Product data', 'acez-seo' ), 'description' => __( 'Price, currency, SKU, and availability go into the Product/Offer node in schema.org, letting Google show the price and availability directly in search results. If WooCommerce is active, this data is pulled automatically from the product and the fields below are ignored.', 'acez-seo' ), 'example' => '', ), 'lite_analysis' => array( 'title' => __( 'Content analysis (Lite)', 'acez-seo' ), 'description' => __( 'Enter the phrase this post should be found for — the lights below check whether it appears in the SEO title, meta description, heading and first paragraph (literal match, no inflection). Also: title/description length within the recommended range, word count, and image alt texts. A gray light means the check is inactive (e.g. no phrase set) — that\'s not an error. The Pro version understands Polish inflection and synonyms, scores readability, and runs an AI content review.', 'acez-seo' ), 'example' => '', ), 'robots_txt_bots' => array( 'title' => __( 'Blocking bots', 'acez-seo' ), 'description' => __( 'Checking a bot adds a "Disallow: /" rule for it in robots.txt, asking it not to index/visit the site. This mainly applies to bots that train AI models (e.g. GPTBot, Google-Extended) — blocking them doesn\'t affect visibility in regular Google/Bing search. This is a request, not a safeguard — well-behaved bots will honor it, malicious ones may ignore it.', 'acez-seo' ), 'example' => '', ), 'robots_txt_custom' => array( 'title' => __( 'Custom robots.txt rules', 'acez-seo' ), 'description' => __( 'Raw text appended to the end of robots.txt — for advanced cases not covered by the bot list above (e.g. blocking a specific directory). Use robots.txt syntax (User-agent / Disallow / Allow).', 'acez-seo' ), 'example' => "User-agent: *\nDisallow: /wp-admin/", ), 'gsc_verification' => array( 'title' => __( 'Google Search Console verification', 'acez-seo' ), 'description' => __( 'Confirms to Google that you own the site — this lets Search Console show you data about how Google sees and indexes your pages. You\'ll find the code in Search Console under the "HTML tag" verification method — copy just the "content" attribute value, not the whole tag.', 'acez-seo' ), 'example' => '', ), 'bing_verification' => array( 'title' => __( 'Bing Webmaster Tools verification', 'acez-seo' ), 'description' => __( 'Confirms ownership of the site for Bing (and therefore also for DuckDuckGo and Yahoo, which use Bing\'s index). You will find the code in Bing Webmaster Tools under the "HTML Meta Tag" verification option — paste only the content value.', 'acez-seo' ), 'example' => '', ), 'yandex_verification' => array( 'title' => __( 'Yandex Webmaster verification', 'acez-seo' ), 'description' => __( 'Confirms ownership of the site for Yandex — worth setting up if your audience includes Russian-speaking markets. The code is in Yandex Webmaster under the "Meta tag" verification method.', 'acez-seo' ), 'example' => '', ), 'pinterest_verification' => array( 'title' => __( 'Pinterest verification', 'acez-seo' ), 'description' => __( 'Confirms the site to Pinterest, which unlocks analytics for Pins pointing at your pages and shows your profile on them. The code comes from Pinterest business settings → Claim your website → Add HTML tag.', 'acez-seo' ), 'example' => '', ), 'baidu_verification' => array( 'title' => __( 'Baidu Webmaster verification', 'acez-seo' ), 'description' => __( 'Confirms ownership of the site for Baidu, the dominant search engine in China. Only relevant if you actually target that market — otherwise leave it empty.', 'acez-seo' ), 'example' => '', ), 'facebook_verification' => array( 'title' => __( 'Facebook / Meta domain verification', 'acez-seo' ), 'description' => __( 'Confirms the domain to Meta Business Manager, which is required before you can control how your links look when shared and before you can use the domain in ad campaigns. The code comes from Business Settings → Brand Safety → Domains.', 'acez-seo' ), 'example' => '', ), 'gtm' => array( 'title' => __( 'Google Tag Manager', 'acez-seo' ), 'description' => __( 'Lets you manage multiple tracking codes (Analytics, ad pixels, etc.) from one place, without editing the site\'s code for every change. You\'ll find the Container ID in Tag Manager, in the GTM-XXXXXXX format.', 'acez-seo' ), 'example' => 'GTM-XXXXXXX', ), 'ga4' => array( 'title' => __( 'Google Analytics (GA4)', 'acez-seo' ), 'description' => __( 'Site traffic statistics. You will find the Measurement ID in Google Analytics: Admin → Data streams → your site (format G-XXXXXXXXXX). If Analytics is connected through Google Tag Manager, do not configure it here a second time. Legacy Universal Analytics IDs (UA-…) are not supported — the service has been shut down by Google.', 'acez-seo' ), 'example' => 'G-XXXXXXXXXX', ), 'hotjar' => array( 'title' => __( 'Hotjar', 'acez-seo' ), 'description' => __( 'A tool for heatmaps and user session recordings — shows how people actually use your site. You\'ll find the Site ID in the Hotjar dashboard under Site Settings.', 'acez-seo' ), 'example' => '', ), 'hide_from_search' => array( 'title' => __( 'Hiding from search engines', 'acez-seo' ), 'description' => __( 'A global indexing kill switch: every page gets noindex/nofollow (regardless of per-post settings) and the XML sitemap stops working. It is a request to robots, not an access block — the site remains publicly reachable. Typical use: development and staging versions. Don\'t forget to turn it off in production!', 'acez-seo' ), 'example' => '', ), 'conflict_override' => array( 'title' => __( 'Force Open Graph/Twitter Cards', 'acez-seo' ), 'description' => __( 'When another active SEO plugin is detected, Acez SEO AI by default disables ALL of its own meta tags (title, description, canonical, Open Graph, Twitter Cards) to avoid duplicating that plugin’s tags. This switch narrows that down to one safe exception: our Open Graph/Twitter Cards take over, and the corresponding tags in the detected plugin are disabled (without modifying its saved settings) — the title, meta description and canonical STILL come from that plugin. Visible only when we have verified support for the detected plugin (currently: Rank Math).', 'acez-seo' ), 'example' => '', ), 'license' => array( 'title' => __( 'License key', 'acez-seo' ), 'description' => __( 'The free version works without a key and remains fully functional. This field is prepared for future Pro features — once they launch, an entered key will unlock them automatically, without reinstalling the plugin.', 'acez-seo' ), 'example' => '', ), 'migrate_seo' => array( 'title' => __( 'Migrate SEO Data', 'acez-seo' ), 'description' => __( 'Moves SEO data from the detected plugin into Acez SEO AI: per-post titles and descriptions, canonical, robots settings (index/follow) and the Open Graph image, plus archive titles/descriptions (Slim SEO, Yoast). Template variables (e.g. Yoast\'s %%title%% or AIOSEO\'s #post_title) are automatically translated to ours. Always start with "Preview" to see the scale of changes without saving anything.', 'acez-seo' ), 'example' => '', ), ); // Attached centrally (not per-entry above) so the illustration choke // point — and its disable filter — lives in ONE place. Entries added // by the Pro addon via the filter below simply won't have these two // keys, which the popover renderers already treat as "nothing to // show" — no base-entry shape change required for Pro compatibility. foreach ( $content as $key => &$entry ) { $entry['illustration'] = HelpIllustrations::get( (string) $key ); $entry['video_url'] = ''; } unset( $entry ); /** * Filters the contextual help content (title/description/example per key). * * @param array> $content */ return (array) apply_filters( 'acez_seo_help_content', $content ); } /** * @return array{title: string, description: string, example: string, illustration: string, video_url: string} */ public static function get( string $key ): array { $all = self::all(); return $all[ $key ] ?? array( 'title' => '', 'description' => '', 'example' => '', 'illustration' => '', 'video_url' => '', ); } }