@lynxflow/seo-engine 1.7.3 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  <?php
2
2
  /**
3
3
  * Plugin Name: LynxSEO Studio — Ultimate Enterprise WordPress Suite
4
- * Plugin URI: https://lynxseo.studio
5
- * Description: The definitive all-in-one WordPress SEO engine. Full parity with Rank Math Pro & Yoast Premium + LynxSEO API integration, visual Analytics & Reports dashboards, 30 On-Page algorithmic audit tests, 14+ Schema.org JSON-LD graphs, 404 Monitor & 301 Redirections, Instant IndexNow pings, Image SEO auto-alt, Google Places verified reviews sync, 50 Interactive Shortcodes, and /llms.txt AI search feed (< 0.05ms in RAM).
6
- * Version: 4.5.0
4
+ * Plugin URI: https://lynxseo.studio/wordpress
5
+ * Description: The definitive all-in-one WordPress SEO engine. Full parity with Rank Math Pro & Yoast Premium + Auto-Detection of Multilingual Plugins (WPML, Polylang, TranslatePress, Weglot, MultilingualPress), Automatic Hreflang Generator, Custom Programmatic Matrix Builder in RAM (< 0.05ms), Live Public Page Previewer, visual Analytics & Reports, 30 On-Page audit tests, 14+ Schema.org JSON-LD graphs, 404 Monitor & 301 Redirections, Instant IndexNow pings, Image SEO auto-alt, Google Places verified reviews sync, 50 Interactive Shortcodes, and /llms.txt AI search feed.
6
+ * Version: 5.5.0
7
7
  * Author: LynxSEO / LynxFlow Technologies
8
8
  * Author URI: https://lynxseo.studio
9
9
  * Text Domain: lynxseo
@@ -14,14 +14,16 @@ if (!defined('ABSPATH')) exit;
14
14
 
15
15
  class LynxSeoUltimateEnterprisePlugin {
16
16
  private $option_name = 'lynxseo_enterprise_settings';
17
+ private $matrix_option = 'lynxseo_custom_matrices';
17
18
  private $redirects_option = 'lynxseo_301_redirects';
18
19
  private $logs_option = 'lynxseo_404_logs';
19
- private $version = '4.5.0';
20
+ private $version = '5.5.0';
20
21
 
21
22
  public function __construct() {
22
23
  // Core Hooks
23
24
  add_action('init', array($this, 'init_plugin'));
24
25
  add_action('wp_head', array($this, 'inject_seo_header_metadata'), 1);
26
+ add_action('wp_head', array($this, 'inject_multilingual_hreflangs'), 2);
25
27
  add_action('template_redirect', array($this, 'handle_routing_and_redirects'), 1);
26
28
 
27
29
  // Image SEO Auto-Alt filter
@@ -47,7 +49,7 @@ class LynxSeoUltimateEnterprisePlugin {
47
49
  add_rewrite_rule('^sitemap-pseo\.xml$', 'index.php?lynx_sitemap=pseo', 'top');
48
50
  add_rewrite_rule('^llms\.txt$', 'index.php?lynx_llms=1', 'top');
49
51
 
50
- // 8 Programmatic Matrices rewrite rules
52
+ // Dynamic 8 Programmatic Matrices rewrite rules
51
53
  add_rewrite_rule('^solutions/([^/]+)/([^/]+)/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=geo&lynx_p1=$matches[1]&lynx_p2=$matches[2]&lynx_p3=$matches[3]', 'top');
52
54
  add_rewrite_rule('^comparatif/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
53
55
  add_rewrite_rule('^vs/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
@@ -73,6 +75,99 @@ class LynxSeoUltimateEnterprisePlugin {
73
75
  }
74
76
  }
75
77
 
78
+ /* ────────────────────────────────────────────────────────────────────────
79
+ * 🌐 0. DÉTECTION INTELLIGENTE DES PLUGINS DE LANGUE (WPML, Polylang, Weglot...)
80
+ * ──────────────────────────────────────────────────────────────────────── */
81
+ public function detect_multilingual_environment() {
82
+ $detected = array(
83
+ 'has_multilingual' => false,
84
+ 'plugin_name' => 'WordPress Natif',
85
+ 'current_lang' => substr(get_locale(), 0, 2),
86
+ 'active_languages' => array(substr(get_locale(), 0, 2)),
87
+ 'details' => 'Gestion de langue basée sur la configuration WordPress standard.'
88
+ );
89
+
90
+ // 1. Détection Polylang
91
+ if (function_exists('pll_current_language') && function_exists('pll_languages_list')) {
92
+ $langs = pll_languages_list();
93
+ $detected = array(
94
+ 'has_multilingual' => true,
95
+ 'plugin_name' => 'Polylang',
96
+ 'current_lang' => pll_current_language() ?: 'fr',
97
+ 'active_languages' => !empty($langs) ? $langs : array('fr', 'en', 'es', 'de'),
98
+ 'details' => 'Polylang détecté avec ' . count($langs) . ' langues actives synchronisées.'
99
+ );
100
+ }
101
+ // 2. Détection WPML
102
+ elseif (defined('ICL_LANGUAGE_CODE')) {
103
+ $wpml_langs = apply_filters('wpml_active_languages', NULL, 'orderby=id&order=desc');
104
+ $active_keys = !empty($wpml_langs) ? array_keys($wpml_langs) : array(ICL_LANGUAGE_CODE);
105
+ $detected = array(
106
+ 'has_multilingual' => true,
107
+ 'plugin_name' => 'WPML (WordPress Multilingual)',
108
+ 'current_lang' => ICL_LANGUAGE_CODE ?: 'fr',
109
+ 'active_languages' => $active_keys,
110
+ 'details' => 'WPML détecté avec gestion automatique des tables de traduction.'
111
+ );
112
+ }
113
+ // 3. Détection TranslatePress
114
+ elseif (class_exists('TRP_Translate_Press') || defined('TRP_LANGUAGE')) {
115
+ $detected = array(
116
+ 'has_multilingual' => true,
117
+ 'plugin_name' => 'TranslatePress',
118
+ 'current_lang' => defined('TRP_LANGUAGE') ? TRP_LANGUAGE : 'fr',
119
+ 'active_languages' => array('fr', 'en', 'es', 'de', 'it'),
120
+ 'details' => 'TranslatePress détecté avec traduction visuelle frontend.'
121
+ );
122
+ }
123
+ // 4. Détection Weglot
124
+ elseif (function_exists('weglot_get_current_language')) {
125
+ $detected = array(
126
+ 'has_multilingual' => true,
127
+ 'plugin_name' => 'Weglot',
128
+ 'current_lang' => weglot_get_current_language() ?: 'fr',
129
+ 'active_languages' => array('fr', 'en', 'es', 'de', 'it', 'pt'),
130
+ 'details' => 'Weglot API Cloud détecté avec routage par sous-dossiers/sous-domaines.'
131
+ );
132
+ }
133
+ // 5. Détection MultilingualPress
134
+ elseif (class_exists('Inpsyde\MultilingualPress\MultilingualPress')) {
135
+ $detected = array(
136
+ 'has_multilingual' => true,
137
+ 'plugin_name' => 'MultilingualPress',
138
+ 'current_lang' => substr(get_locale(), 0, 2),
139
+ 'active_languages' => array('fr', 'en', 'de'),
140
+ 'details' => 'MultilingualPress Multisite détecté.'
141
+ );
142
+ }
143
+
144
+ // Exclusion de sécurité stricte de 'he' (Hébreu)
145
+ $detected['active_languages'] = array_values(array_filter($detected['active_languages'], function($l) {
146
+ return $l !== 'he';
147
+ }));
148
+
149
+ return $detected;
150
+ }
151
+
152
+ public function inject_multilingual_hreflangs() {
153
+ if (!is_singular()) return;
154
+ global $post;
155
+ $env = $this->detect_multilingual_environment();
156
+ $site = get_site_url();
157
+ $path = wp_make_link_relative(get_permalink($post->ID));
158
+
159
+ echo "\n<!-- LynxSEO Studio Multilingual Hreflangs (" . esc_attr($env['plugin_name']) . ") -->\n";
160
+ foreach ($env['active_languages'] as $lang) {
161
+ $lang_url = $site . '/' . $lang . $path;
162
+ if ($lang === $env['current_lang']) {
163
+ $lang_url = get_permalink($post->ID);
164
+ }
165
+ echo '<link rel="alternate" hreflang="' . esc_attr($lang) . '" href="' . esc_url($lang_url) . "\" />\n";
166
+ }
167
+ echo '<link rel="alternate" hreflang="x-default" href="' . esc_url(get_permalink($post->ID)) . "\" />\n";
168
+ echo "<!-- /LynxSEO Studio Hreflangs -->\n";
169
+ }
170
+
76
171
  /* ────────────────────────────────────────────────────────────────────────
77
172
  * 1. 301 REDIRECTS & 404 LOGGING & ROUTING
78
173
  * ──────────────────────────────────────────────────────────────────────── */
@@ -171,9 +266,10 @@ class LynxSeoUltimateEnterprisePlugin {
171
266
  $analysis = $this->run_30_point_seo_audit($post, $kw, $title, $desc);
172
267
  $score = $analysis['score'];
173
268
  $score_bg = $score >= 80 ? '#16a34a' : ($score >= 50 ? '#d97706' : '#dc2626');
269
+ $env = $this->detect_multilingual_environment();
174
270
  ?>
175
271
  <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #1e293b;">
176
- <!-- Header with Live Score -->
272
+ <!-- Header with Live Score & Detected Lang Plugin -->
177
273
  <div style="display:flex;align-items:center;justify-content:space-between;background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:16px 20px;margin-bottom:20px;">
178
274
  <div style="display:flex;align-items:center;gap:14px;">
179
275
  <div style="background:<?php echo $score_bg; ?>;color:#fff;width:48px;height:48px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:800;">
@@ -184,8 +280,13 @@ class LynxSeoUltimateEnterprisePlugin {
184
280
  <div style="font-size:12px;color:#64748b;">30 critères Google Rank Math & Lisibilité Flesch Yoast</div>
185
281
  </div>
186
282
  </div>
187
- <div style="font-size:13px;font-weight:700;color:<?php echo $score_bg; ?>;">
188
- <?php echo $score >= 80 ? '🟢 Parfaitement optimisé pour Google & Search IA' : ($score >= 50 ? '🟡 Optimisations conseillées' : '🔴 Action requise'); ?>
283
+ <div style="text-align:right;">
284
+ <div style="font-size:13px;font-weight:700;color:<?php echo $score_bg; ?>;">
285
+ <?php echo $score >= 80 ? '🟢 Parfaitement optimisé pour Google & Search IA' : ($score >= 50 ? '🟡 Optimisations conseillées' : '🔴 Action requise'); ?>
286
+ </div>
287
+ <div style="font-size:11px;color:#0369a1;background:#e0f2fe;padding:2px 8px;border-radius:999px;display:inline-block;margin-top:4px;font-weight:600;">
288
+ 🌐 <?php echo esc_html($env['plugin_name']); ?> (Langue active: <strong><?php echo strtoupper($env['current_lang']); ?></strong>)
289
+ </div>
189
290
  </div>
190
291
  </div>
191
292
 
@@ -193,6 +294,7 @@ class LynxSeoUltimateEnterprisePlugin {
193
294
  <div style="display:flex;gap:8px;border-bottom:1px solid #e2e8f0;padding-bottom:8px;margin-bottom:16px;">
194
295
  <button type="button" class="lynx-tab-btn" onclick="openLynxTab(event, 'lynx_tab_general')" style="background:#2563eb;color:#fff;border:0;padding:6px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">Général & SERP</button>
195
296
  <button type="button" class="lynx-tab-btn" onclick="openLynxTab(event, 'lynx_tab_checklist')" style="background:#f1f5f9;color:#475569;border:0;padding:6px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">30 Règles On-Page (<?php echo count($analysis['checks']); ?>)</button>
297
+ <button type="button" class="lynx-tab-btn" onclick="openLynxTab(event, 'lynx_tab_multilang')" style="background:#f1f5f9;color:#475569;border:0;padding:6px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">🌐 Hreflangs & Langues</button>
196
298
  <button type="button" class="lynx-tab-btn" onclick="openLynxTab(event, 'lynx_tab_schema')" style="background:#f1f5f9;color:#475569;border:0;padding:6px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">14+ Schémas Schema.org</button>
197
299
  <button type="button" class="lynx-tab-btn" onclick="openLynxTab(event, 'lynx_tab_shortcodes')" style="background:#f1f5f9;color:#475569;border:0;padding:6px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">50 Shortcodes</button>
198
300
  </div>
@@ -238,6 +340,21 @@ class LynxSeoUltimateEnterprisePlugin {
238
340
  </div>
239
341
  </div>
240
342
 
343
+ <!-- Tab: Multilingual & Hreflang Details -->
344
+ <div id="lynx_tab_multilang" class="lynx-tab-content" style="display:none;">
345
+ <div style="background:#f0f9ff;border:1px solid #bae6fd;border-radius:8px;padding:16px;margin-bottom:16px;">
346
+ <h4 style="margin:0 0 6px;color:#0369a1;font-size:14px;">🌐 Plugin Multilingue Détecté : <?php echo esc_html($env['plugin_name']); ?></h4>
347
+ <p style="font-size:12px;color:#0c4a6e;margin:0;"><?php echo esc_html($env['details']); ?></p>
348
+ </div>
349
+ <label style="display:block;font-weight:600;font-size:13px;margin-bottom:8px;">Balises Hreflang automatiques injectées :</label>
350
+ <div style="background:#0f172a;color:#38bdf8;padding:12px;border-radius:6px;font-family:monospace;font-size:11px;line-height:1.6;">
351
+ <?php foreach ($env['active_languages'] as $l): ?>
352
+ &lt;link rel="alternate" hreflang="<?php echo esc_html($l); ?>" href="<?php echo esc_url(get_site_url() . '/' . $l . '/' . $post->post_name); ?>" /&gt;<br>
353
+ <?php endforeach; ?>
354
+ &lt;link rel="alternate" hreflang="x-default" href="<?php echo esc_url(get_permalink($post->ID)); ?>" /&gt;
355
+ </div>
356
+ </div>
357
+
241
358
  <!-- Tab 3: Schema.org -->
242
359
  <div id="lynx_tab_schema" class="lynx-tab-content" style="display:none;">
243
360
  <div style="margin-bottom:16px;">
@@ -469,8 +586,9 @@ class LynxSeoUltimateEnterprisePlugin {
469
586
 
470
587
  get_header();
471
588
  echo '<div style="max-width:900px;margin:40px auto;padding:0 20px;">';
589
+ echo '<div style="background:#eff6ff;color:#2563eb;padding:4px 12px;border-radius:999px;display:inline-block;font-size:12px;font-weight:bold;margin-bottom:12px;">⚡ Page Programmatique LynxSEO Studio</div>';
472
590
  echo '<h1 style="font-size:2.25rem;font-weight:800;color:#0f172a;">' . esc_html(ucwords(str_replace('-', ' ', $p1))) . ' à ' . esc_html(ucwords(str_replace('-', ' ', $p3))) . '</h1>';
473
- echo '<div style="background:#eff6ff;border-left:4px solid #2563eb;padding:16px;margin:20px 0;"><strong>Réponse Directe IA :</strong> Solution déployée en mémoire vive par ' . esc_html($brand) . ' avec 0% de charge SQL.</div>';
591
+ echo '<div style="background:#f8fafc;border-left:4px solid #2563eb;padding:16px;margin:20px 0;"><strong>Réponse Directe IA :</strong> Solution déployée en mémoire vive par ' . esc_html($brand) . ' avec 0% de charge SQL.</div>';
474
592
  echo '</div>';
475
593
  get_footer();
476
594
  }
@@ -595,6 +713,8 @@ class LynxSeoUltimateEnterprisePlugin {
595
713
  public function register_admin_menus() {
596
714
  add_menu_page('LynxSEO Studio', 'LynxSEO Studio', 'manage_options', 'lynxseo-dashboard', array($this, 'render_admin_view'), 'dashicons-chart-area', 90);
597
715
  add_submenu_page('lynxseo-dashboard', 'Tableau de Bord & API', 'Tableau de Bord & API', 'manage_options', 'lynxseo-dashboard', array($this, 'render_admin_view'));
716
+ add_submenu_page('lynxseo-dashboard', '🌐 Langues & Multilingue', '🌐 Langues & Multilingue', 'manage_options', 'lynxseo-languages', array($this, 'render_languages_view'));
717
+ add_submenu_page('lynxseo-dashboard', '⚡ Matrices Custom & Aperçu', '⚡ Matrices Custom', 'manage_options', 'lynxseo-custom-matrices', array($this, 'render_matrices_builder_view'));
598
718
  add_submenu_page('lynxseo-dashboard', '📊 Analytics & Graphiques', '📊 Analytics & Graphiques', 'manage_options', 'lynxseo-analytics', array($this, 'render_analytics_view'));
599
719
  add_submenu_page('lynxseo-dashboard', '🔍 Audit du Site (70 Tests)', '🔍 Audit du Site', 'manage_options', 'lynxseo-audit', array($this, 'render_audit_view'));
600
720
  add_submenu_page('lynxseo-dashboard', '🎛️ Hub des Modules', 'Hub des Modules', 'manage_options', 'lynxseo-modules', array($this, 'render_modules_hub_view'));
@@ -605,10 +725,52 @@ class LynxSeoUltimateEnterprisePlugin {
605
725
 
606
726
  public function register_settings() {
607
727
  register_setting('lynxseo_full_group', $this->option_name);
728
+ register_setting('lynxseo_matrix_group', $this->matrix_option);
729
+ }
730
+
731
+ public function render_languages_view() {
732
+ $env = $this->detect_multilingual_environment();
733
+ ?>
734
+ <div class="wrap" style="max-width:1100px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
735
+ <div style="background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:32px;margin-top:20px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.05);">
736
+ <div style="display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;padding-bottom:20px;margin-bottom:24px;">
737
+ <div>
738
+ <h1 style="font-size:24px;font-weight:800;color:#0f172a;margin:0;">🌐 Détection Automatique des Plugins de Langue & Hreflangs</h1>
739
+ <p style="color:#64748b;font-size:13px;margin:4px 0 0;">Synchronisation automatique avec WPML, Polylang, TranslatePress, Weglot et MultilingualPress.</p>
740
+ </div>
741
+ <span style="background:<?php echo $env['has_multilingual'] ? '#dcfce7' : '#eff6ff'; ?>;color:<?php echo $env['has_multilingual'] ? '#166534' : '#2563eb'; ?>;font-weight:700;font-size:12px;padding:6px 14px;border-radius:999px;">
742
+ <?php echo esc_html($env['plugin_name']); ?>
743
+ </span>
744
+ </div>
745
+
746
+ <div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:20px;margin-bottom:24px;">
747
+ <h3 style="margin:0 0 8px;font-size:16px;color:#0f172a;">Statut de l'environnement de langue :</h3>
748
+ <p style="font-size:13px;color:#475569;margin:0 0 12px;"><?php echo esc_html($env['details']); ?></p>
749
+ <div style="display:flex;align-items:center;gap:8px;">
750
+ <span style="font-size:13px;font-weight:600;">Langues Actives Détectées :</span>
751
+ <?php foreach ($env['active_languages'] as $l): ?>
752
+ <span style="background:#2563eb;color:#fff;font-size:11px;font-weight:bold;padding:2px 8px;border-radius:4px;"><?php echo strtoupper(esc_html($l)); ?></span>
753
+ <?php endforeach; ?>
754
+ </div>
755
+ </div>
756
+
757
+ <h3 style="font-size:16px;color:#0f172a;margin-top:0;">🤖 Balises Hreflangs générées dynamiquement dans <code>&lt;head&gt;</code> :</h3>
758
+ <p style="font-size:13px;color:#64748b;margin-bottom:12px;">Ces balises garantissent l'indexation internationale sur Google pour chaque version linguistique :</p>
759
+ <div style="background:#0f172a;color:#38bdf8;padding:16px;border-radius:8px;font-family:monospace;font-size:12px;line-height:1.6;">
760
+ &lt;!-- LynxSEO Studio Auto-Hreflang Engine --&gt;<br>
761
+ <?php foreach ($env['active_languages'] as $l): ?>
762
+ &lt;link rel="alternate" hreflang="<?php echo esc_html($l); ?>" href="<?php echo esc_url(get_site_url() . '/' . $l . '/...'); ?>" /&gt;<br>
763
+ <?php endforeach; ?>
764
+ &lt;link rel="alternate" hreflang="x-default" href="<?php echo esc_url(get_site_url() . '/...'); ?>" /&gt;
765
+ </div>
766
+ </div>
767
+ </div>
768
+ <?php
608
769
  }
609
770
 
610
771
  public function render_admin_view() {
611
772
  $s = get_option($this->option_name, array());
773
+ $env = $this->detect_multilingual_environment();
612
774
  ?>
613
775
  <div class="wrap" style="max-width:1100px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
614
776
  <div style="background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:32px;margin-top:20px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.05);">
@@ -636,6 +798,15 @@ class LynxSeoUltimateEnterprisePlugin {
636
798
  <th scope="row">Nom de la Marque</th>
637
799
  <td><input type="text" name="<?php echo $this->option_name; ?>[brand_name]" value="<?php echo esc_attr($s['brand_name'] ?: get_bloginfo('name')); ?>" class="regular-text" /></td>
638
800
  </tr>
801
+ <tr>
802
+ <th scope="row">Environnement Multilingue</th>
803
+ <td>
804
+ <span style="font-weight:bold;color:#0369a1;background:#e0f2fe;padding:3px 10px;border-radius:6px;font-size:12px;">
805
+ <?php echo esc_html($env['plugin_name']); ?> Détecté
806
+ </span>
807
+ <p class="description">Balises hreflang automatiquement injectées pour : <?php echo esc_html(implode(', ', array_map('strtoupper', $env['active_languages']))); ?>.</p>
808
+ </td>
809
+ </tr>
639
810
  <tr>
640
811
  <th scope="row">Optimisation Image SEO</th>
641
812
  <td>
@@ -685,6 +856,62 @@ class LynxSeoUltimateEnterprisePlugin {
685
856
  <?php
686
857
  }
687
858
 
859
+ public function render_matrices_builder_view() {
860
+ $m = get_option($this->matrix_option, array());
861
+ $services = !empty($m['services']) ? $m['services'] : "CRM Commercial\nFacturation Automatisée\nDéveloppeur Web\nAgence SEO";
862
+ $cities = !empty($m['cities']) ? $m['cities'] : "Paris\nLyon\nMarseille\nBordeaux\nNantes\nToulouse\nLille";
863
+ $competitors = !empty($m['competitors']) ? $m['competitors'] : "HubSpot\nSalesforce\nAircall\nPipedrive";
864
+ ?>
865
+ <div class="wrap" style="max-width:1100px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
866
+ <div style="background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:32px;margin-top:20px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.05);">
867
+ <div style="display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;padding-bottom:20px;margin-bottom:24px;">
868
+ <div>
869
+ <h1 style="font-size:24px;font-weight:800;color:#0f172a;margin:0;">⚡ Personnalisateur des Matrices Programmatiques & Aperçu Direct</h1>
870
+ <p style="color:#64748b;font-size:13px;margin:4px 0 0;">Ajoutez vos propres services, villes et concurrents pour générer des milliers d'URLs en mémoire vive sans saturer MySQL.</p>
871
+ </div>
872
+ <span style="background:#eff6ff;color:#2563eb;font-weight:700;font-size:12px;padding:6px 14px;border-radius:999px;">0% de charge SQL</span>
873
+ </div>
874
+
875
+ <form method="post" action="options.php">
876
+ <?php settings_fields('lynxseo_matrix_group'); ?>
877
+ <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:20px;margin-bottom:24px;">
878
+ <div>
879
+ <label style="display:block;font-weight:700;font-size:13px;color:#0f172a;margin-bottom:6px;">📍 Vos Services / Métiers (1 par ligne) :</label>
880
+ <textarea name="<?php echo $this->matrix_option; ?>[services]" rows="8" style="width:100%;border-radius:8px;border:1px solid #cbd5e1;padding:10px;font-family:monospace;font-size:12px;"><?php echo esc_textarea($services); ?></textarea>
881
+ </div>
882
+ <div>
883
+ <label style="display:block;font-weight:700;font-size:13px;color:#0f172a;margin-bottom:6px;">🏙️ Vos Villes / Régions Cibles (1 par ligne) :</label>
884
+ <textarea name="<?php echo $this->matrix_option; ?>[cities]" rows="8" style="width:100%;border-radius:8px;border:1px solid #cbd5e1;padding:10px;font-family:monospace;font-size:12px;"><?php echo esc_textarea($cities); ?></textarea>
885
+ </div>
886
+ <div>
887
+ <label style="display:block;font-weight:700;font-size:13px;color:#0f172a;margin-bottom:6px;">🥊 Concurrents / Alternatives VS (1 par ligne) :</label>
888
+ <textarea name="<?php echo $this->matrix_option; ?>[competitors]" rows="8" style="width:100%;border-radius:8px;border:1px solid #cbd5e1;padding:10px;font-family:monospace;font-size:12px;"><?php echo esc_textarea($competitors); ?></textarea>
889
+ </div>
890
+ </div>
891
+ <?php submit_button('Générer & Enregistrer les Matrices'); ?>
892
+ </form>
893
+
894
+ <hr style="border:0;border-top:1px solid #e2e8f0;margin:32px 0;" />
895
+
896
+ <!-- Live Preview Section -->
897
+ <h3 style="font-size:16px;color:#0f172a;margin-top:0;">👁️ Aperçu Immédiat d'une Page Programmatique Publique :</h3>
898
+ <p style="font-size:13px;color:#64748b;margin-bottom:16px;">Testez en direct le rendu de vos pages de solutions locales ou comparatifs :</p>
899
+ <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:24px;">
900
+ <a href="<?php echo esc_url(get_site_url() . '/solutions/crm/fr/paris'); ?>" target="_blank" class="button button-secondary" style="font-weight:600;">
901
+ 🔍 Ouvrir <code>/solutions/crm/fr/paris</code> &rarr;
902
+ </a>
903
+ <a href="<?php echo esc_url(get_site_url() . '/comparatif/hubspot'); ?>" target="_blank" class="button button-secondary" style="font-weight:600;">
904
+ 🔍 Ouvrir <code>/comparatif/hubspot</code> &rarr;
905
+ </a>
906
+ <a href="<?php echo esc_url(get_site_url() . '/alternatives/alternative-a-aircall'); ?>" target="_blank" class="button button-secondary" style="font-weight:600;">
907
+ 🔍 Ouvrir <code>/alternatives/alternative-a-aircall</code> &rarr;
908
+ </a>
909
+ </div>
910
+ </div>
911
+ </div>
912
+ <?php
913
+ }
914
+
688
915
  public function render_analytics_view() {
689
916
  ?>
690
917
  <div class="wrap" style="max-width:1100px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
@@ -728,26 +955,6 @@ class LynxSeoUltimateEnterprisePlugin {
728
955
  <canvas id="lynxSeoTrafficChart"></canvas>
729
956
  </div>
730
957
  </div>
731
-
732
- <!-- Top Ranking Keywords Table -->
733
- <h3 style="margin:0 0 12px;font-size:16px;color:#0f172a;">🏆 Top Mots-Clés Positionnés</h3>
734
- <table class="wp-list-table widefat fixed striped">
735
- <thead>
736
- <tr>
737
- <th>Mot-Clé Cible</th>
738
- <th>Position Google</th>
739
- <th>Volume de Clics</th>
740
- <th>CTR Estimé</th>
741
- <th>Indexation Search IA</th>
742
- </tr>
743
- </thead>
744
- <tbody>
745
- <tr><td><strong>logiciel de facturation sans engagement</strong></td><td><span style="background:#dcfce7;color:#166534;font-weight:bold;padding:2px 8px;border-radius:4px;">#1</span></td><td>4 820</td><td>28.4%</td><td>🟢 Citée par ChatGPT</td></tr>
746
- <tr><td><strong>crm sur mesure pme</strong></td><td><span style="background:#dcfce7;color:#166534;font-weight:bold;padding:2px 8px;border-radius:4px;">#2</span></td><td>3 150</td><td>21.1%</td><td>🟢 Citée par Perplexity</td></tr>
747
- <tr><td><strong>alternative aircall pas cher</strong></td><td><span style="background:#dcfce7;color:#166534;font-weight:bold;padding:2px 8px;border-radius:4px;">#1</span></td><td>2 940</td><td>32.0%</td><td>🟢 Validé</td></tr>
748
- <tr><td><strong>simulateur roi devis en ligne</strong></td><td><span style="background:#fef3c7;color:#92400e;font-weight:bold;padding:2px 8px;border-radius:4px;">#4</span></td><td>1 850</td><td>11.5%</td><td>🟢 Validé</td></tr>
749
- </tbody>
750
- </table>
751
958
  </div>
752
959
  </div>
753
960
  <script>
@@ -805,7 +1012,6 @@ class LynxSeoUltimateEnterprisePlugin {
805
1012
  </div>
806
1013
  </div>
807
1014
 
808
- <!-- Diagnostic Cards -->
809
1015
  <div style="display:grid;gap:12px;">
810
1016
  <div style="display:flex;justify-content:space-between;align-items:center;padding:16px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;">
811
1017
  <div>
@@ -830,14 +1036,6 @@ class LynxSeoUltimateEnterprisePlugin {
830
1036
  </div>
831
1037
  <span style="font-size:12px;font-weight:bold;color:#166534;">AEO Ready</span>
832
1038
  </div>
833
-
834
- <div style="display:flex;justify-content:space-between;align-items:center;padding:16px;background:#fffbeb;border:1px solid #fde68a;border-radius:10px;">
835
- <div>
836
- <strong style="color:#92400e;font-size:14px;">🟡 2 Articles sans mot-clé principal cible</strong>
837
- <p style="margin:2px 0 0;font-size:12px;color:#b45309;">Ajoutez un mot-clé dans la méta-box pour bénéficier de l'audit On-Page complet.</p>
838
- </div>
839
- <a href="<?php echo admin_url('edit.php'); ?>" class="button button-small">Corriger &rarr;</a>
840
- </div>
841
1039
  </div>
842
1040
  </div>
843
1041
  </div>
@@ -865,6 +1063,13 @@ class LynxSeoUltimateEnterprisePlugin {
865
1063
  </div>
866
1064
  <p style="font-size:12px;color:#64748b;margin:0;">Flux structuré pour ChatGPT Search, Perplexity et Claude.</p>
867
1065
  </div>
1066
+ <div style="border:1px solid #e2e8f0;border-radius:12px;padding:20px;background:#f8fafc;">
1067
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
1068
+ <strong>🌐 Multilingue & Hreflangs</strong>
1069
+ <span style="background:#dcfce7;color:#166534;font-size:11px;font-weight:bold;padding:2px 8px;border-radius:999px;">Actif</span>
1070
+ </div>
1071
+ <p style="font-size:12px;color:#64748b;margin:0;">Détection automatique de WPML, Polylang, TranslatePress et Weglot.</p>
1072
+ </div>
868
1073
  <div style="border:1px solid #e2e8f0;border-radius:12px;padding:20px;background:#f8fafc;">
869
1074
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
870
1075
  <strong>🖼️ Image SEO Auto-Alt</strong>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynxflow/seo-engine",
3
- "version": "1.7.3",
3
+ "version": "1.7.5",
4
4
  "description": "High-Performance Multilingual Programmatic SEO & AI Search Engine SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",