array( 'title' => __( 'Metadata', 'ai-o-optimiser' ), 'eyebrow' => __( 'See what needs fixing', 'ai-o-optimiser' ), 'headline' => __( 'Find and fix metadata issues across your whole site.', 'ai-o-optimiser' ), 'cta' => __( 'Get Metadata with Pro', 'ai-o-optimiser' ), 'caption' => __( 'Representative AI-O Optimiser Pro Metadata workspace — figures illustrative.', 'ai-o-optimiser' ), 'card' => __( 'Every page has a headline in Google. Most sites have dozens that are missing, cut off, or identical to each other.', 'ai-o-optimiser' ), 'hook' => __( 'Every page has a headline in Google. Most sites have dozens that are missing, cut off, or identical to each other.', 'ai-o-optimiser' ), 'cost' => __( 'Scan the site, turn findings into a reviewable queue, and use real search evidence to decide what deserves attention first.', 'ai-o-optimiser' ), 'workflow' => array( __( 'Scan', 'ai-o-optimiser' ), __( 'Generate', 'ai-o-optimiser' ), __( 'Review', 'ai-o-optimiser' ), __( 'Apply', 'ai-o-optimiser' ), ), 'benefits' => array( array( 'icon' => 'search', 'title' => __( 'Metadata scan', 'ai-o-optimiser' ), 'text' => __( 'Find weak or missing titles, descriptions and focus keywords across the site.', 'ai-o-optimiser' ), ), array( 'icon' => 'list-view', 'title' => __( 'Review queue', 'ai-o-optimiser' ), 'text' => __( 'Generate, review, approve or retry suggestions through an operational workflow.', 'ai-o-optimiser' ), ), array( 'icon' => 'chart-line', 'title' => __( 'Search opportunities', 'ai-o-optimiser' ), 'text' => __( 'Use Search Console and Bing evidence to identify pages and queries already close to earning more visibility.', 'ai-o-optimiser' ), ), array( 'icon' => 'category', 'title' => __( 'Category and content opportunities', 'ai-o-optimiser' ), 'text' => __( 'Keep archives purposeful and surface content opportunities from real search demand.', 'ai-o-optimiser' ), ), ), ), 'schema' => array( 'title' => __( 'Schema', 'ai-o-optimiser' ), 'eyebrow' => __( 'See what Google actually receives', 'ai-o-optimiser' ), 'headline' => __( 'Find schema conflicts on the finished page, then fix the real gaps.', 'ai-o-optimiser' ), 'cta' => __( 'Get Schema with Pro', 'ai-o-optimiser' ), 'caption' => __( 'Representative AI-O Optimiser Pro Schema workspace — figures illustrative.', 'ai-o-optimiser' ), 'card' => __( 'A hidden description of your business sits behind every page. Your SEO plugin, your theme and your store plugin each write their own, and they disagree.', 'ai-o-optimiser' ), 'hook' => __( 'Behind every page is a hidden description of your business that Google and AI assistants read.', 'ai-o-optimiser' ), 'cost' => __( 'Audit the rendered page, identify which provider owns each schema type, fix genuine gaps and verify the public JSON-LD after the change.', 'ai-o-optimiser' ), 'workflow' => array( __( 'Audit', 'ai-o-optimiser' ), __( 'Issues', 'ai-o-optimiser' ), __( 'Fix', 'ai-o-optimiser' ), __( 'Verify', 'ai-o-optimiser' ), ), 'benefits' => array( array( 'icon' => 'visibility', 'title' => __( 'Audit finished pages', 'ai-o-optimiser' ), 'text' => __( 'Read the schema Google and AI systems can actually see, not just what a plugin says it generated.', 'ai-o-optimiser' ), ), array( 'icon' => 'warning', 'title' => __( 'Find conflicts', 'ai-o-optimiser' ), 'text' => __( 'Show where themes, SEO plugins and commerce plugins describe the same page differently.', 'ai-o-optimiser' ), ), array( 'icon' => 'admin-plugins', 'title' => __( 'Respect native schema', 'ai-o-optimiser' ), 'text' => __( 'Leave correct Rank Math, Yoast, WooCommerce and theme output alone instead of duplicating it.', 'ai-o-optimiser' ), ), array( 'icon' => 'yes-alt', 'title' => __( 'Verify the fix', 'ai-o-optimiser' ), 'text' => __( 'Recheck the live page after remediation before calling an issue resolved.', 'ai-o-optimiser' ), ), ), ), 'local' => array( 'title' => __( 'Business details (NAP)', 'ai-o-optimiser' ), 'eyebrow' => __( 'Keep business identity consistent', 'ai-o-optimiser' ), 'headline' => __( 'Keep your name, address and phone aligned across the places that matter.', 'ai-o-optimiser' ), 'cta' => __( 'Get NAP management with Pro', 'ai-o-optimiser' ), 'caption' => __( 'The same three details, as three different sources hold them', 'ai-o-optimiser' ), 'card' => __( 'Your name, address and phone drift apart across your site, Google and every directory that lists you. This finds the mismatches and keeps track of them.', 'ai-o-optimiser' ), 'hook' => __( 'Your name, address and phone number - your NAP - appear in your footer, on your contact page, inside your structured data, and on every directory that has ever listed you.', 'ai-o-optimiser' ), 'cost' => __( 'Confirm the business baseline once, compare it with your own site and external listings, then keep a review trail for the differences that need attention.', 'ai-o-optimiser' ), 'workflow' => array( __( 'Confirm', 'ai-o-optimiser' ), __( 'Compare', 'ai-o-optimiser' ), __( 'Review', 'ai-o-optimiser' ), __( 'Recheck', 'ai-o-optimiser' ), ), 'benefits' => array( array( 'icon' => 'businessperson', 'title' => __( 'Confirm your baseline', 'ai-o-optimiser' ), 'text' => __( 'Set the business name, address and phone that other sources should match.', 'ai-o-optimiser' ), ), array( 'icon' => 'location', 'title' => __( 'Compare important sources', 'ai-o-optimiser' ), 'text' => __( 'Review your site, Google Business Profile and the directories that matter to the business.', 'ai-o-optimiser' ), ), array( 'icon' => 'search', 'title' => __( 'Review mismatches', 'ai-o-optimiser' ), 'text' => __( 'Separate genuine inconsistencies from items that need manual confirmation or call-tracking context.', 'ai-o-optimiser' ), ), array( 'icon' => 'update', 'title' => __( 'Keep a follow-up trail', 'ai-o-optimiser' ), 'text' => __( 'Record what was confirmed, rejected or could not be verified so drift can be checked again later.', 'ai-o-optimiser' ), ), ), ), ); } /** Menu callback for the Metadata workspace. */ public static function render_workspace_metadata() { self::render_workspace( 'metadata' ); } /** Menu callback for the Schema workspace. */ public static function render_workspace_schema() { self::render_workspace( 'schema' ); } /** Menu callback for the NAP workspace. */ public static function render_workspace_local() { self::render_workspace( 'local' ); } /** * Render a workspace as a preview of what the paid version does. * * @param string $key Feature key. * @return void */ public static function render_workspace( $key ) { $features = self::features(); if ( ! isset( $features[ $key ] ) ) { return; } $feature = $features[ $key ]; ?>

$step ) : ?>

$other ) : if ( $other_key === $key ) { continue; } ?>

' . esc_html__( 'dashboard', 'ai-o-optimiser' ) . '' ); ?>

', esc_url( $image ), /* translators: %s: feature name. */ esc_attr( sprintf( __( 'The %s workspace in AI-O Optimiser Pro', 'ai-o-optimiser' ), $title ) ), $width && $height ? ' width="' . (int) $width . '" height="' . (int) $height . '"' : '' ); return; } /* translators: %s: feature name. */ $label = sprintf( __( 'Diagram of the %s workspace layout', 'ai-o-optimiser' ), $title ); echo ''; echo ''; echo ''; echo ''; if ( 'metadata' === $key ) { $rows = array( array( 'crit', 'crit' ), array( 'ok', 'crit' ), array( 'warn', 'ok' ), array( 'warn', 'warn' ), array( 'ok', 'ok' ), array( 'ok', 'ok' ) ); echo ''; echo ''; $y = 50; foreach ( $rows as $row ) { echo ''; $x = 168; foreach ( $row as $state ) { echo ''; $x += 74; } $y += 22; } } elseif ( 'schema' === $key ) { /* * Two sources describing one page, and the disagreement between them. * * This was drawn without a single word on it, and read as abstract * shapes to the first person who opened it -- which is a fair verdict * on a diagram whose whole point is *who* disagrees with *whom*. The * NAP drawing below labels its three sources and is legible; this one * now does the same. */ echo '' . esc_html__( 'Who describes this page', 'ai-o-optimiser' ) . ''; echo ''; echo '' . esc_html__( 'SEO plugin', 'ai-o-optimiser' ) . ''; echo ''; echo ''; echo '' . esc_html__( 'Theme', 'ai-o-optimiser' ) . ''; echo ''; echo ''; echo ''; echo ''; echo '' . esc_html__( 'Finished page', 'ai-o-optimiser' ) . ''; echo ''; echo ''; echo ''; echo ''; echo '' . esc_html__( 'Two answers reach Google. It picks one.', 'ai-o-optimiser' ) . ''; } else { /* * The same three details - name, address, phone - as three * different sources hold them. The point of the picture is that * two agree and one does not, and that the reader can see which * of the three details is the one that drifted. */ echo ''; $rows = array( 'N', 'A', 'P' ); $sources = array( 'Your site', 'Google', 'Directory' ); $row_y = array( 84, 110, 136 ); // Row letters down the left, outside the cards. foreach ( $rows as $r => $letter ) { echo '' . esc_html( $letter ) . ''; } foreach ( $sources as $i => $source ) { $x = 34 + ( $i * 96 ); // The third source has the phone number wrong. echo ''; echo '' . esc_html( $source ) . ''; echo ''; foreach ( $rows as $r => $letter ) { $bad = ( 2 === $i && 2 === $r ); $y = $row_y[ $r ]; $fill = $bad ? '#f7dcd6' : '#d6f5ec'; $line = $bad ? '#a33a22' : '#0e7c66'; echo ''; echo ''; } } // Name and address match across all three; the phone does not. echo ''; echo '' . esc_html__( 'One source disagrees', 'ai-o-optimiser' ) . ''; } echo ''; } /** * A real product screenshot bundled only into the Free build. * * @param string $key Feature key. * @return array|array{} */ private static function bundled_preview( $key ) { $previews = array( 'metadata' => array( 'assets/pro-preview/metadata-workspace.webp', 960, 540 ), 'schema' => array( 'assets/pro-preview/schema-workspace.webp', 960, 540 ), ); if ( ! isset( $previews[ $key ] ) ) { return array(); } $file = $previews[ $key ][0]; if ( ! is_readable( AI_O_Optimiser_PLUGIN_DIR . $file ) ) { return array(); } return array( 'url' => AI_O_Optimiser_PLUGIN_URL . $file, 'width' => (int) $previews[ $key ][1], 'height' => (int) $previews[ $key ][2], ); } /** * Fill for a status pill in the metadata diagram. * * @param string $state ok|warn|crit. * @return string */ private static function state_fill( $state ) { $fills = array( 'ok' => '#e8f4ec', 'warn' => '#fbf1dc', 'crit' => '#fbeaea' ); return isset( $fills[ $state ] ) ? $fills[ $state ] : '#f3f2f2'; } /** * Outline for a status pill in the metadata diagram. * * @param string $state ok|warn|crit. * @return string */ private static function state_line( $state ) { $lines = array( 'ok' => '#1a7f37', 'warn' => '#8a6100', 'crit' => '#b32d2e' ); return isset( $lines[ $state ] ) ? $lines[ $state ] : '#c9c5c2'; } /** * A compact summary for the foot of the Settings screen. * * @return void */ public static function render_settings_section() { ?>

* block on admin_head, which is what the plugin directory asks for. Plain * string literals: CSS carries no quotes, so there is nothing to capture. */ public static function enqueue_styles() { AI_O_Optimiser_Admin::add_inline_style( '.ai-o-optimiser-pro-hero { display: grid; grid-template-columns: minmax(22rem,.9fr) minmax(30rem,1.2fr); gap: 2.25rem; align-items: center; background: #fff; border: 1px solid #d8d5d2; padding: 2rem; max-width: 88rem; }' . '.ai-o-optimiser-pro-hero__copy { min-width: 0; }' . '.ai-o-optimiser-pro-hero__art { min-width: 0; display: flex; flex-direction: column; gap: .55rem; }' . '.ai-o-optimiser-pro-art, .ai-o-optimiser-pro-shot { width: 100%; height: auto; display: block; border: 1px solid #d8d5d2; border-radius: 8px; box-shadow: 0 14px 36px rgba(32,30,29,.10); }' . '.ai-o-optimiser-pro-caption { font-size: .78rem; color: #6b6764; }' . '.ai-o-optimiser-pro-eyebrow { margin: 0 0 .45rem; color: #0e7c66; font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }' . '.ai-o-optimiser-pro-headline { margin: 0 0 .75rem; max-width: 15em; font-size: 1.8rem; line-height: 1.12; }' . '.ai-o-optimiser-pro-cost { margin: 0 0 1rem; color: #6b6764; max-width: 43em; font-size: .95rem; line-height: 1.55; }' . '.ai-o-optimiser-pro-workflow { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0 0 1.15rem; }' . '.ai-o-optimiser-pro-workflow__step { display: inline-flex; align-items: center; min-height: 1.8rem; padding: .15rem .55rem; border: 1px solid #cce9e2; border-radius: 999px; background: #f2fbf8; color: #0e7c66; font-size: .78rem; font-weight: 600; }' . '.ai-o-optimiser-pro-workflow__arrow { color: #8c8f94; }' . '.ai-o-optimiser-pro-benefits { display: grid; gap: .8rem; margin: 0 0 1.25rem; }' . '.ai-o-optimiser-pro-benefit { display: grid; grid-template-columns: 2.3rem minmax(0,1fr); gap: .7rem; align-items: start; }' . '.ai-o-optimiser-pro-benefit__icon { width: 2.3rem; height: 2.3rem; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; background: #e6f7f3; color: #0e7c66; font-size: 1.1rem; line-height: 2.3rem; }' . '.ai-o-optimiser-pro-benefit__copy { display: flex; flex-direction: column; gap: .12rem; }' . '.ai-o-optimiser-pro-benefit__copy strong { font-size: .9rem; color: #1d2327; }' . '.ai-o-optimiser-pro-benefit__copy span { font-size: .82rem; line-height: 1.45; color: #50575e; }' . '.ai-o-optimiser-pro-actions { margin: 0 0 .75rem; display: flex; flex-wrap: wrap; align-items: center; gap: .85rem; }' . '.ai-o-optimiser-pro-secondary { font-weight: 600; text-decoration: none; }' . '.ai-o-optimiser-pro-secondary:hover, .ai-o-optimiser-pro-secondary:focus { text-decoration: underline; }' . '.ai-o-optimiser-pro-price { margin: 0 0 .35rem; font-size: .9375rem; font-weight: 600; color: #1d2327; }' . '.ai-o-optimiser-pro-reassure { margin: 0; font-size: .8125rem; color: #6b6764; max-width: 42em; }' . '.ai-o-optimiser-pro-more { margin-top: 2rem; max-width: 88rem; }' . '.ai-o-optimiser-pro-more h2 { font-size: 1.05rem; margin-bottom: .75rem; }' . '.ai-o-optimiser-pro-more__grid { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); max-width: 88rem; }' . '.ai-o-optimiser-pro-more__item { background: #fff; border: 1px solid #d8d5d2; padding: .9rem 1rem; display: flex; flex-direction: column; gap: .3rem; }' . '.ai-o-optimiser-pro-more__item strong { font-size: .9rem; }' . '.ai-o-optimiser-pro-more__item span { font-size: .8125rem; color: #6b6764; }' . '@media (max-width: 1100px) { .ai-o-optimiser-pro-hero { grid-template-columns: 1fr; } .ai-o-optimiser-pro-headline { max-width: 24em; } .ai-o-optimiser-pro-hero__art { max-width: 58rem; } }' ); } }