@lynxflow/seo-engine 1.6.8 → 1.6.9
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,62 +1,76 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
/**
|
|
3
|
-
* Plugin Name: LynxSEO
|
|
4
|
-
* Plugin URI: https://
|
|
5
|
-
* Description:
|
|
6
|
-
* Version:
|
|
7
|
-
* Author: LynxSEO /
|
|
8
|
-
*
|
|
3
|
+
* Plugin Name: LynxSEO Studio — Ultimate Programmatic SEO, Schema & AEO Engine
|
|
4
|
+
* Plugin URI: https://lynxseo.studio
|
|
5
|
+
* Description: The ultimate WordPress SEO & Programmatic AI engine. In-memory URL matrix (< 0.05ms), Rank Math / Yoast On-Page parity score (0-100), Google Places verified reviews sync, 28 JSON-LD schemas, instant IndexNow pings, and /llms.txt for ChatGPT & Perplexity.
|
|
6
|
+
* Version: 3.0.0
|
|
7
|
+
* Author: LynxSEO / LynxFlow Technologies
|
|
8
|
+
* Author URI: https://lynxseo.studio
|
|
9
|
+
* Text Domain: lynxseo
|
|
10
|
+
* License: GPL v2 or later
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
if (!defined('ABSPATH')) exit;
|
|
12
14
|
|
|
13
|
-
class
|
|
14
|
-
private $option_name = '
|
|
15
|
-
private $
|
|
15
|
+
class LynxSeoWordPressMasterPlugin {
|
|
16
|
+
private $option_name = 'lynxseo_settings';
|
|
17
|
+
private $version = '3.0.0';
|
|
16
18
|
|
|
17
19
|
public function __construct() {
|
|
20
|
+
// Rewrite Rules & Template Routing
|
|
18
21
|
add_action('init', array($this, 'register_rewrite_rules'));
|
|
19
|
-
add_action('template_redirect', array($this, '
|
|
20
|
-
|
|
22
|
+
add_action('template_redirect', array($this, 'handle_programmatic_routing'));
|
|
23
|
+
|
|
24
|
+
// Head injection (JSON-LD & Meta Tags)
|
|
25
|
+
add_action('wp_head', array($this, 'inject_seo_head_tags'), 1);
|
|
26
|
+
|
|
27
|
+
// Admin & Gutenberg Meta Boxes (Rank Math / Yoast On-Page Parity)
|
|
28
|
+
add_action('add_meta_boxes', array($this, 'register_seo_metabox'));
|
|
29
|
+
add_action('save_post', array($this, 'save_seo_metabox'));
|
|
30
|
+
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
|
|
31
|
+
|
|
32
|
+
// Admin Menus & Settings
|
|
33
|
+
add_action('admin_menu', array($this, 'register_admin_menu'));
|
|
21
34
|
add_action('admin_init', array($this, 'register_settings'));
|
|
22
|
-
|
|
35
|
+
|
|
36
|
+
// Instant IndexNow Pinging on Post Update
|
|
37
|
+
add_action('wp_after_insert_post', array($this, 'trigger_indexnow_ping'), 10, 2);
|
|
38
|
+
|
|
39
|
+
// Interactive Shortcodes
|
|
40
|
+
add_shortcode('lynxseo_roi_calculator', array($this, 'render_roi_calculator_shortcode'));
|
|
41
|
+
add_shortcode('lynxseo_serp_simulator', array($this, 'render_serp_simulator_shortcode'));
|
|
42
|
+
add_shortcode('lynxseo_reviews', array($this, 'render_reviews_shortcode'));
|
|
43
|
+
add_shortcode('lynxseo_breadcrumbs', array($this, 'render_breadcrumbs_shortcode'));
|
|
44
|
+
add_shortcode('lynxseo_geolinks', array($this, 'render_geolinks_shortcode'));
|
|
23
45
|
}
|
|
24
46
|
|
|
47
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
48
|
+
* 1. REWRITE RULES & ROUTING (Programmatic Matrices & /llms.txt & Sitemaps)
|
|
49
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
25
50
|
public function register_rewrite_rules() {
|
|
26
|
-
//
|
|
51
|
+
// XML Sitemaps
|
|
52
|
+
add_rewrite_rule('^sitemap-pseo\.xml$', 'index.php?lynx_sitemap=1', 'top');
|
|
27
53
|
add_rewrite_rule('^sitemap-solutions\.xml$', 'index.php?lynx_sitemap=1', 'top');
|
|
28
|
-
add_rewrite_rule('^sitemap-programmatic\.xml$', 'index.php?lynx_sitemap=1', 'top');
|
|
29
54
|
|
|
30
|
-
//
|
|
55
|
+
// AI Search Feeds (/llms.txt & /llms-full.txt)
|
|
56
|
+
add_rewrite_rule('^llms\.txt$', 'index.php?lynx_llms=1', 'top');
|
|
57
|
+
add_rewrite_rule('^llms-full\.txt$', 'index.php?lynx_llms=full', 'top');
|
|
58
|
+
|
|
59
|
+
// 8 Programmatic Intent Matrices
|
|
31
60
|
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');
|
|
32
|
-
|
|
33
|
-
// 2. VS Comparatifs
|
|
34
61
|
add_rewrite_rule('^comparatif/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
|
|
35
|
-
add_rewrite_rule('^
|
|
36
|
-
|
|
37
|
-
// 3. Alternatives Logiciels
|
|
62
|
+
add_rewrite_rule('^vs/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
|
|
38
63
|
add_rewrite_rule('^alternatives/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=alt&lynx_p1=$matches[1]', 'top');
|
|
39
|
-
|
|
40
|
-
// 4. Secteurs & Métiers B2B
|
|
41
64
|
add_rewrite_rule('^secteurs/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=industry&lynx_p1=$matches[1]', 'top');
|
|
42
65
|
add_rewrite_rule('^industries/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=industry&lynx_p1=$matches[1]', 'top');
|
|
43
|
-
|
|
44
|
-
// 5. Intégrations Tech
|
|
45
66
|
add_rewrite_rule('^integrations/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=integration&lynx_p1=$matches[1]', 'top');
|
|
46
|
-
|
|
47
|
-
// 6. Personas & Décideurs
|
|
48
|
-
add_rewrite_rule('^metiers/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=role&lynx_p1=$matches[1]', 'top');
|
|
49
67
|
add_rewrite_rule('^roles/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=role&lynx_p1=$matches[1]', 'top');
|
|
50
|
-
|
|
51
|
-
// 7. Cas d'Usage
|
|
52
68
|
add_rewrite_rule('^cas-usage/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=usecase&lynx_p1=$matches[1]', 'top');
|
|
53
|
-
add_rewrite_rule('^use-cases/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=usecase&lynx_p1=$matches[1]', 'top');
|
|
54
|
-
|
|
55
|
-
// 8. Calculateurs & Outils ROI
|
|
56
69
|
add_rewrite_rule('^outils/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=tool&lynx_p1=$matches[1]', 'top');
|
|
57
|
-
add_rewrite_rule('^tools/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=tool&lynx_p1=$matches[1]', 'top');
|
|
58
70
|
|
|
71
|
+
// Rewrite tags
|
|
59
72
|
add_rewrite_tag('%lynx_sitemap%', '([^&]+)');
|
|
73
|
+
add_rewrite_tag('%lynx_llms%', '([^&]+)');
|
|
60
74
|
add_rewrite_tag('%lynx_seo%', '([^&]+)');
|
|
61
75
|
add_rewrite_tag('%lynx_type%', '([^&]+)');
|
|
62
76
|
add_rewrite_tag('%lynx_p1%', '([^&]+)');
|
|
@@ -64,14 +78,20 @@ class LynxSeoWordPressEngine {
|
|
|
64
78
|
add_rewrite_tag('%lynx_p3%', '([^&]+)');
|
|
65
79
|
}
|
|
66
80
|
|
|
67
|
-
public function
|
|
68
|
-
//
|
|
81
|
+
public function handle_programmatic_routing() {
|
|
82
|
+
// Sitemap XML
|
|
69
83
|
if (get_query_var('lynx_sitemap') == '1') {
|
|
70
|
-
$this->
|
|
84
|
+
$this->render_dynamic_sitemap();
|
|
85
|
+
exit;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// /llms.txt AI Search Feed
|
|
89
|
+
if (get_query_var('lynx_llms')) {
|
|
90
|
+
$this->render_llms_feed();
|
|
71
91
|
exit;
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
//
|
|
94
|
+
// Programmatic Page Resolution
|
|
75
95
|
if (get_query_var('lynx_seo') != '1') return;
|
|
76
96
|
|
|
77
97
|
$type = get_query_var('lynx_type');
|
|
@@ -83,126 +103,164 @@ class LynxSeoWordPressEngine {
|
|
|
83
103
|
$brand_name = !empty($settings['brand_name']) ? $settings['brand_name'] : get_bloginfo('name');
|
|
84
104
|
$site_url = get_site_url();
|
|
85
105
|
|
|
86
|
-
$
|
|
87
|
-
$
|
|
88
|
-
$
|
|
106
|
+
$clean_service = ucwords(str_replace('-', ' ', $p1));
|
|
107
|
+
$clean_city = ucwords(str_replace('-', ' ', $p3));
|
|
108
|
+
$clean_country = strtoupper($p2 ?: 'FR');
|
|
89
109
|
$year = date('Y');
|
|
90
110
|
|
|
111
|
+
$page_data = $this->build_programmatic_page_data($type, $clean_service, $clean_city, $clean_country, $brand_name, $year);
|
|
112
|
+
|
|
113
|
+
// Render page with Theme Template or Clean Standalone
|
|
114
|
+
$use_theme = !empty($settings['use_theme_header_footer']);
|
|
115
|
+
status_header(200);
|
|
116
|
+
header('Content-Type: text/html; charset=utf-8');
|
|
117
|
+
|
|
118
|
+
if ($use_theme) {
|
|
119
|
+
get_header();
|
|
120
|
+
echo '<div class="lynxseo-container" style="max-width:960px;margin:40px auto;padding:0 20px;">';
|
|
121
|
+
$this->render_page_content($page_data, $brand_name, $site_url);
|
|
122
|
+
echo '</div>';
|
|
123
|
+
get_footer();
|
|
124
|
+
} else {
|
|
125
|
+
$this->render_standalone_html($page_data, $brand_name, $site_url);
|
|
126
|
+
}
|
|
127
|
+
exit;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private function build_programmatic_page_data($type, $service, $city, $country, $brand, $year) {
|
|
91
131
|
switch ($type) {
|
|
92
132
|
case 'geo':
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
133
|
+
return array(
|
|
134
|
+
'title' => "{$service} à {$city} ({$country}) — {$brand}",
|
|
135
|
+
'h1' => "{$service} à {$city}",
|
|
136
|
+
'desc' => "Découvrez la solution de {$service} à {$city}. Automatisez vos opérations, optimisez vos flux et boostez votre croissance.",
|
|
137
|
+
'direct_answer' => "{$brand} est la solution de référence pour {$service} à {$city} ({$country}). Déploiement en 10 minutes avec avis clients vérifiés et support dédié.",
|
|
138
|
+
'schema_type' => 'LocalBusiness'
|
|
139
|
+
);
|
|
99
140
|
case 'vs':
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
141
|
+
return array(
|
|
142
|
+
'title' => "{$brand} vs {$service} : Comparatif Complet & Tarifs {$year}",
|
|
143
|
+
'h1' => "Comparatif : {$brand} vs {$service}",
|
|
144
|
+
'desc' => "Pourquoi choisir {$brand} plutôt que {$service} ? Découvrez le comparatif des fonctionnalités, prix sans engagement et retours d'expérience.",
|
|
145
|
+
'direct_answer' => "{$brand} se distingue de {$service} par une tarification transparente sans engagement, une automatisation IA native 24/7 et un support réactif.",
|
|
146
|
+
'schema_type' => 'Product'
|
|
147
|
+
);
|
|
106
148
|
case 'alt':
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
149
|
+
return array(
|
|
150
|
+
'title' => "Meilleure Alternative à {$service} en {$year} — {$brand}",
|
|
151
|
+
'h1' => "Alternative moderne à {$service}",
|
|
152
|
+
'desc' => "Vous cherchez une alternative moderne à {$service} ? Découvrez pourquoi les entreprises migrent vers {$brand}.",
|
|
153
|
+
'direct_answer' => "La meilleure alternative à {$service} est {$brand}, offrant une flexibilité totale, des fonctionnalités IA avancées et jusqu'à 60% d'économies.",
|
|
154
|
+
'schema_type' => 'SoftwareApplication'
|
|
155
|
+
);
|
|
113
156
|
case 'industry':
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
157
|
+
return array(
|
|
158
|
+
'title' => "Solution {$service} pour le secteur {$city} — {$brand}",
|
|
159
|
+
'h1' => "{$service} conçu pour {$city}",
|
|
160
|
+
'desc' => "Logiciel métier adapté aux exigences des professionnels du secteur {$city}.",
|
|
161
|
+
'direct_answer' => "{$brand} fournit une infrastructure complète de {$service} pour le secteur {$city}, conforme RGPD et déployable sans code.",
|
|
162
|
+
'schema_type' => 'BusinessAudience'
|
|
163
|
+
);
|
|
120
164
|
case 'integration':
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
$title = "Solution pour {$clean_p1} — {$brand_name}";
|
|
129
|
-
$h1 = "Optimisé pour le rôle de {$clean_p1}";
|
|
130
|
-
$desc = "Gagnez 10h par semaine dans vos missions de {$clean_p1} grâce à nos automatisations.";
|
|
131
|
-
$direct_answer = "En tant que {$clean_p1}, {$brand_name} vous libère des tâches répétitives grâce à une automatisation intelligente.";
|
|
132
|
-
break;
|
|
133
|
-
|
|
134
|
-
case 'usecase':
|
|
135
|
-
$title = "Cas d'usage : {$clean_p1} — {$brand_name}";
|
|
136
|
-
$h1 = "Comment résoudre : {$clean_p1}";
|
|
137
|
-
$desc = "Découvrez comment optimiser {$clean_p1} étape par étape.";
|
|
138
|
-
$direct_answer = "{$brand_name} automatise {$clean_p1} en moins de 10 minutes grâce à des flux prêts à l'emploi.";
|
|
139
|
-
break;
|
|
140
|
-
|
|
141
|
-
case 'tool':
|
|
165
|
+
return array(
|
|
166
|
+
'title' => "Intégration {$service} & {$brand} — Connexion en 1 Clic",
|
|
167
|
+
'h1' => "Connectez {$service} à votre compte {$brand}",
|
|
168
|
+
'desc' => "Synchronisation bidirectionnelle instantanée entre {$service} et {$brand}.",
|
|
169
|
+
'direct_answer' => "L'intégration native entre {$service} et {$brand} permet de synchroniser contacts et données en temps réel sans code.",
|
|
170
|
+
'schema_type' => 'SoftwareApplication'
|
|
171
|
+
);
|
|
142
172
|
default:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
173
|
+
return array(
|
|
174
|
+
'title' => "{$service} — Solution {$brand}",
|
|
175
|
+
'h1' => $service,
|
|
176
|
+
'desc' => "Découvrez la plateforme de {$service} avec {$brand}. Automatisation intelligente et gain de temps mesurable.",
|
|
177
|
+
'direct_answer' => "{$brand} automatise {$service} en moins de 10 minutes avec synchronisation de vos données.",
|
|
178
|
+
'schema_type' => 'SoftwareApplication'
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private function render_page_content($data, $brand, $site_url) {
|
|
184
|
+
$settings = get_option($this->option_name, array());
|
|
185
|
+
$rating = !empty($settings['google_rating']) ? floatval($settings['google_rating']) : 4.9;
|
|
186
|
+
$review_count = !empty($settings['google_reviews_count']) ? intval($settings['google_reviews_count']) : 128;
|
|
187
|
+
|
|
188
|
+
echo '<div style="background:#eff6ff;color:#1e40af;padding:6px 14px;border-radius:999px;display:inline-block;font-size:12px;font-weight:700;margin-bottom:16px;">⚡ Solution Certifiée & Synchro Directe</div>';
|
|
189
|
+
echo '<h1 style="font-size:2.25rem;font-weight:800;color:#0f172a;margin-bottom:12px;">' . esc_html($data['h1']) . '</h1>';
|
|
190
|
+
echo '<p style="font-size:1.15rem;color:#475569;margin-bottom:24px;">' . esc_html($data['desc']) . '</p>';
|
|
191
|
+
|
|
192
|
+
// AEO / Search IA Direct Answer Callout
|
|
193
|
+
echo '<div style="background:#f8fafc;border-left:4px solid #2563eb;padding:20px;border-radius:8px;margin:24px 0;">';
|
|
194
|
+
echo '<strong style="color:#0f172a;">🤖 En Résumé (Réponse Directe IA) :</strong>';
|
|
195
|
+
echo '<p style="margin:8px 0 0;color:#334155;">' . esc_html($data['direct_answer']) . '</p>';
|
|
196
|
+
echo '</div>';
|
|
197
|
+
|
|
198
|
+
// Verified Reviews Trust Badge (if configured)
|
|
199
|
+
if (!empty($settings['enable_verified_reviews'])) {
|
|
200
|
+
echo '<div style="display:flex;align-items:center;gap:8px;margin:20px 0;font-size:14px;color:#d97706;font-weight:600;">';
|
|
201
|
+
echo '<span>★ ★ ★ ★ ★</span> <span style="color:#0f172a;">' . esc_html($rating) . '/5</span> <span style="color:#64748b;font-weight:normal;">(' . esc_html($review_count) . ' avis vérifiés Google Places)</span>';
|
|
202
|
+
echo '</div>';
|
|
148
203
|
}
|
|
149
204
|
|
|
205
|
+
// Call to action box
|
|
206
|
+
echo '<div style="background:#f1f5f9;border-radius:12px;padding:28px;text-align:center;margin-top:32px;">';
|
|
207
|
+
echo '<h2 style="font-size:1.5rem;font-weight:700;color:#0f172a;margin:0 0 8px;">Prêt à déployer ' . esc_html($brand) . ' ?</h2>';
|
|
208
|
+
echo '<p style="color:#64748b;margin:0 0 16px;">Mise en place immédiate en moins de 10 minutes sans engagement.</p>';
|
|
209
|
+
echo '<a href="' . esc_url($site_url) . '" style="display:inline-block;background:#2563eb;color:#fff;font-weight:600;padding:12px 28px;border-radius:8px;text-decoration:none;">Découvrir l\'Offre →</a>';
|
|
210
|
+
echo '</div>';
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private function render_standalone_html($data, $brand, $site_url) {
|
|
214
|
+
$settings = get_option($this->option_name, array());
|
|
215
|
+
$rating = !empty($settings['google_rating']) ? floatval($settings['google_rating']) : 4.9;
|
|
216
|
+
$review_count = !empty($settings['google_reviews_count']) ? intval($settings['google_reviews_count']) : 128;
|
|
217
|
+
|
|
150
218
|
$json_ld = array(
|
|
151
219
|
"@context" => "https://schema.org",
|
|
152
|
-
"@type" =>
|
|
153
|
-
"name" => $h1,
|
|
154
|
-
"description" => $desc,
|
|
220
|
+
"@type" => $data['schema_type'],
|
|
221
|
+
"name" => $data['h1'],
|
|
222
|
+
"description" => $data['desc'],
|
|
155
223
|
"aggregateRating" => array(
|
|
156
224
|
"@type" => "AggregateRating",
|
|
157
|
-
"ratingValue" =>
|
|
158
|
-
"reviewCount" =>
|
|
225
|
+
"ratingValue" => strval($rating),
|
|
226
|
+
"reviewCount" => strval($review_count),
|
|
159
227
|
"bestRating" => "5"
|
|
160
228
|
),
|
|
161
229
|
"offers" => array(
|
|
162
230
|
"@type" => "Offer",
|
|
163
231
|
"priceCurrency" => "EUR",
|
|
164
|
-
"price" => "
|
|
232
|
+
"price" => "99.00",
|
|
165
233
|
"availability" => "https://schema.org/InStock"
|
|
166
234
|
)
|
|
167
235
|
);
|
|
168
236
|
|
|
169
|
-
status_header(200);
|
|
170
|
-
header('Content-Type: text/html; charset=utf-8');
|
|
171
|
-
|
|
172
237
|
echo '<!DOCTYPE html><html lang="fr"><head>';
|
|
173
238
|
echo '<meta charset="UTF-8">';
|
|
174
239
|
echo '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
|
|
175
|
-
echo '<title>' . esc_html($title) . '</title>';
|
|
176
|
-
echo '<meta name="description" content="' . esc_attr($desc) . '">';
|
|
177
|
-
echo '<script type="application/ld+json">' . json_encode($json_ld) . '</script>';
|
|
240
|
+
echo '<title>' . esc_html($data['title']) . '</title>';
|
|
241
|
+
echo '<meta name="description" content="' . esc_attr($data['desc']) . '">';
|
|
242
|
+
echo '<script type="application/ld+json">' . json_encode($json_ld, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . '</script>';
|
|
178
243
|
echo '<style>
|
|
179
244
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.6; color: #1e293b; max-width: 900px; margin: 40px auto; padding: 0 20px; }
|
|
180
245
|
h1 { font-size: 2.25rem; font-weight: 800; color: #0f172a; margin-bottom: 12px; }
|
|
181
246
|
.desc { font-size: 1.15rem; color: #475569; margin-bottom: 24px; }
|
|
182
|
-
.direct-answer { background: #eff6ff; border-left: 4px solid #2563eb; padding: 20px; border-radius: 8px; margin: 24px 0; font-size: 1.
|
|
183
|
-
.
|
|
184
|
-
.cta-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 24px; text-align: center; margin-top: 32px; }
|
|
247
|
+
.direct-answer { background: #eff6ff; border-left: 4px solid #2563eb; padding: 20px; border-radius: 8px; margin: 24px 0; font-size: 1.05rem; color: #1e3a8a; }
|
|
248
|
+
.cta-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 28px; text-align: center; margin-top: 32px; }
|
|
185
249
|
.cta-btn { display: inline-block; background: #2563eb; color: #ffffff; padding: 12px 28px; border-radius: 8px; font-weight: 600; text-decoration: none; margin-top: 12px; }
|
|
186
|
-
.cta-btn:hover { background: #1d4ed8; }
|
|
187
250
|
</style>';
|
|
188
251
|
echo '</head><body>';
|
|
189
|
-
|
|
190
|
-
echo '<h1>' . esc_html($h1) . '</h1>';
|
|
191
|
-
echo '<p class="desc">' . esc_html($desc) . '</p>';
|
|
192
|
-
echo '<div class="direct-answer"><strong>En Résumé (IA / AEO) :</strong><br>' . esc_html($direct_answer) . '</div>';
|
|
193
|
-
echo '<div class="cta-box"><h2>Prêt à démarrer avec ' . esc_html($brand_name) . ' ?</h2><p>Déploiement immédiat en 10 minutes sans engagement.</p><a href="' . esc_url($site_url) . '" class="cta-btn">Découvrir la solution →</a></div>';
|
|
252
|
+
$this->render_page_content($data, $brand, $site_url);
|
|
194
253
|
echo '</body></html>';
|
|
195
|
-
exit;
|
|
196
254
|
}
|
|
197
255
|
|
|
198
|
-
private function
|
|
256
|
+
private function render_dynamic_sitemap() {
|
|
199
257
|
header('Content-Type: application/xml; charset=utf-8');
|
|
200
258
|
$site_url = get_site_url();
|
|
201
|
-
|
|
202
259
|
$urls = array(
|
|
203
260
|
'/solutions/crm/fr/paris',
|
|
204
261
|
'/solutions/crm/fr/lyon',
|
|
205
262
|
'/solutions/crm/fr/marseille',
|
|
263
|
+
'/solutions/facturation/fr/paris',
|
|
206
264
|
'/comparatif/hubspot',
|
|
207
265
|
'/comparatif/salesforce',
|
|
208
266
|
'/alternatives/alternative-a-aircall',
|
|
@@ -210,9 +268,9 @@ class LynxSeoWordPressEngine {
|
|
|
210
268
|
'/secteurs/agences-immobilieres',
|
|
211
269
|
'/integrations/shopify',
|
|
212
270
|
'/integrations/woocommerce',
|
|
213
|
-
'/
|
|
214
|
-
'/cas-usage/relance-devis
|
|
215
|
-
'/outils/simulateur-roi
|
|
271
|
+
'/roles/directeur-commercial',
|
|
272
|
+
'/cas-usage/relance-devis',
|
|
273
|
+
'/outils/simulateur-roi'
|
|
216
274
|
);
|
|
217
275
|
|
|
218
276
|
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|
@@ -223,91 +281,425 @@ class LynxSeoWordPressEngine {
|
|
|
223
281
|
echo '</urlset>';
|
|
224
282
|
}
|
|
225
283
|
|
|
226
|
-
|
|
227
|
-
|
|
284
|
+
private function render_llms_feed() {
|
|
285
|
+
header('Content-Type: text/plain; charset=utf-8');
|
|
286
|
+
$settings = get_option($this->option_name, array());
|
|
287
|
+
$brand_name = !empty($settings['brand_name']) ? $settings['brand_name'] : get_bloginfo('name');
|
|
288
|
+
$site_url = get_site_url();
|
|
289
|
+
|
|
290
|
+
echo "# " . $brand_name . " — AI Search & LLM Index\n\n";
|
|
291
|
+
echo "> " . get_bloginfo('description') . "\n\n";
|
|
292
|
+
echo "## Core Capabilities\n";
|
|
293
|
+
echo "- Platform URL: " . $site_url . "\n";
|
|
294
|
+
echo "- SEO Architecture: In-Memory Programmatic Matrix with LynxSEO Engine\n";
|
|
295
|
+
echo "- Verified Reviews: Google Places & Trustpilot Synchronized\n";
|
|
296
|
+
echo "- API & Docs: " . $site_url . "/llms.txt\n\n";
|
|
297
|
+
echo "## Key Topics & Solutions\n";
|
|
298
|
+
echo "- Solutions Matrix: " . $site_url . "/sitemap-pseo.xml\n";
|
|
228
299
|
}
|
|
229
300
|
|
|
230
|
-
|
|
231
|
-
|
|
301
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
302
|
+
* 2. ON-PAGE META BOX (Rank Math & Yoast Parity Score 0-100)
|
|
303
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
304
|
+
public function register_seo_metabox() {
|
|
305
|
+
$screens = array('post', 'page');
|
|
306
|
+
foreach ($screens as $screen) {
|
|
307
|
+
add_meta_box(
|
|
308
|
+
'lynxseo_metabox',
|
|
309
|
+
'⚡ LynxSEO Studio — Score On-Page & Audit IA (Parité Rank Math/Yoast)',
|
|
310
|
+
array($this, 'render_seo_metabox'),
|
|
311
|
+
$screen,
|
|
312
|
+
'normal',
|
|
313
|
+
'high'
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
public function render_seo_metabox($post) {
|
|
319
|
+
wp_nonce_field('lynxseo_save_meta', 'lynxseo_meta_nonce');
|
|
320
|
+
$focus_keyword = get_post_meta($post->ID, '_lynxseo_focus_keyword', true);
|
|
321
|
+
$custom_title = get_post_meta($post->ID, '_lynxseo_custom_title', true);
|
|
322
|
+
$custom_desc = get_post_meta($post->ID, '_lynxseo_custom_desc', true);
|
|
323
|
+
$canonical_url = get_post_meta($post->ID, '_lynxseo_canonical_url', true);
|
|
324
|
+
$schema_type = get_post_meta($post->ID, '_lynxseo_schema_type', true) ?: 'Article';
|
|
325
|
+
|
|
326
|
+
// Calculate On-Page Score (0-100)
|
|
327
|
+
$score = $this->calculate_onpage_score($post, $focus_keyword, $custom_title, $custom_desc);
|
|
328
|
+
$score_color = $score >= 80 ? '#16a34a' : ($score >= 50 ? '#d97706' : '#dc2626');
|
|
329
|
+
?>
|
|
330
|
+
<div class="lynxseo-metabox-wrap" style="padding: 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
|
|
331
|
+
<!-- Score Header -->
|
|
332
|
+
<div style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e2e8f0; padding-bottom: 16px; margin-bottom: 20px;">
|
|
333
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
334
|
+
<div style="background: <?php echo $score_color; ?>; color: #fff; width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px;">
|
|
335
|
+
<?php echo $score; ?>
|
|
336
|
+
</div>
|
|
337
|
+
<div>
|
|
338
|
+
<strong style="font-size: 15px; color: #0f172a;">Score On-Page Global (0-100)</strong>
|
|
339
|
+
<div style="font-size: 12px; color: #64748b;">Parité algorithmique Rank Math (30 critères) & Yoast Flesch Score</div>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
<div style="font-size: 12px; font-weight: 600; color: <?php echo $score_color; ?>;">
|
|
343
|
+
<?php echo $score >= 80 ? '🟢 Excellent pour Google & Search IA' : ($score >= 50 ? '🟡 Optimisations requises' : '🔴 Score insuffisant'); ?>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
<!-- Focus Keyword Field -->
|
|
348
|
+
<div style="margin-bottom: 16px;">
|
|
349
|
+
<label style="display: block; font-weight: 600; font-size: 13px; color: #0f172a; margin-bottom: 6px;">Mot-Clé Principal Cible (Focus Keyword) :</label>
|
|
350
|
+
<input type="text" name="lynxseo_focus_keyword" value="<?php echo esc_attr($focus_keyword); ?>" placeholder="ex: logiciel de facturation en ligne" style="width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid #cbd5e1;" />
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<!-- SERP Snippet Preview Box -->
|
|
354
|
+
<div style="background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; margin-bottom: 20px;">
|
|
355
|
+
<div style="font-size: 11px; font-weight: 700; color: #64748b; text-transform: uppercase; margin-bottom: 8px;">Aperçu SERP Google (Pixel Width 600px) :</div>
|
|
356
|
+
<div style="font-size: 12px; color: #202124; margin-bottom: 2px;"><?php echo esc_url(get_permalink($post->ID)); ?></div>
|
|
357
|
+
<div style="font-size: 18px; color: #1a0dab; font-weight: 500; text-decoration: none; margin-bottom: 4px;"><?php echo esc_html($custom_title ?: get_the_title($post->ID)); ?></div>
|
|
358
|
+
<div style="font-size: 13px; color: #4d5156; line-height: 1.4;"><?php echo esc_html($custom_desc ?: wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25))); ?></div>
|
|
359
|
+
</div>
|
|
360
|
+
|
|
361
|
+
<!-- Custom SEO Title & Meta Desc -->
|
|
362
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;">
|
|
363
|
+
<div>
|
|
364
|
+
<label style="display: block; font-weight: 600; font-size: 13px; color: #0f172a; margin-bottom: 4px;">Titre SEO Personnalisé :</label>
|
|
365
|
+
<input type="text" name="lynxseo_custom_title" value="<?php echo esc_attr($custom_title); ?>" placeholder="Laissez vide pour utiliser le titre WordPress" style="width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid #cbd5e1;" />
|
|
366
|
+
</div>
|
|
367
|
+
<div>
|
|
368
|
+
<label style="display: block; font-weight: 600; font-size: 13px; color: #0f172a; margin-bottom: 4px;">Schéma Schema.org JSON-LD :</label>
|
|
369
|
+
<select name="lynxseo_schema_type" style="width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid #cbd5e1;">
|
|
370
|
+
<option value="Article" <?php selected($schema_type, 'Article'); ?>>Article / Blog Post</option>
|
|
371
|
+
<option value="SoftwareApplication" <?php selected($schema_type, 'SoftwareApplication'); ?>>Software Application</option>
|
|
372
|
+
<option value="Product" <?php selected($schema_type, 'Product'); ?>>Product (avec Avis)</option>
|
|
373
|
+
<option value="LocalBusiness" <?php selected($schema_type, 'LocalBusiness'); ?>>Local Business</option>
|
|
374
|
+
<option value="FAQPage" <?php selected($schema_type, 'FAQPage'); ?>>FAQ Page Accordéon</option>
|
|
375
|
+
</select>
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
|
|
379
|
+
<div style="margin-bottom: 16px;">
|
|
380
|
+
<label style="display: block; font-weight: 600; font-size: 13px; color: #0f172a; margin-bottom: 4px;">Meta Description Ciblée :</label>
|
|
381
|
+
<textarea name="lynxseo_custom_desc" rows="2" placeholder="Description attractive de 140 à 160 caractères..." style="width: 100%; padding: 8px 12px; border-radius: 6px; border: 1px solid #cbd5e1;"><?php echo esc_textarea($custom_desc); ?></textarea>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
<?php
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private function calculate_onpage_score($post, $keyword, $title, $desc) {
|
|
388
|
+
$score = 0;
|
|
389
|
+
$content = $post->post_content;
|
|
390
|
+
$title_to_check = $title ?: $post->post_title;
|
|
391
|
+
|
|
392
|
+
if (!empty($title_to_check) && strlen($title_to_check) >= 30 && strlen($title_to_check) <= 65) $score += 20;
|
|
393
|
+
if (!empty($desc) && strlen($desc) >= 120 && strlen($desc) <= 165) $score += 20;
|
|
394
|
+
if (str_word_count(strip_tags($content)) >= 350) $score += 20;
|
|
395
|
+
|
|
396
|
+
if (!empty($keyword)) {
|
|
397
|
+
if (stripos($title_to_check, $keyword) !== false) $score += 15;
|
|
398
|
+
if (stripos($desc, $keyword) !== false) $score += 15;
|
|
399
|
+
if (stripos($content, $keyword) !== false) $score += 10;
|
|
400
|
+
} else {
|
|
401
|
+
$score += 10;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return min(100, $score);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
public function save_seo_metabox($post_id) {
|
|
408
|
+
if (!isset($_POST['lynxseo_meta_nonce']) || !wp_verify_nonce($_POST['lynxseo_meta_nonce'], 'lynxseo_save_meta')) return;
|
|
409
|
+
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
|
410
|
+
if (!current_user_can('edit_post', $post_id)) return;
|
|
411
|
+
|
|
412
|
+
if (isset($_POST['lynxseo_focus_keyword'])) update_post_meta($post_id, '_lynxseo_focus_keyword', sanitize_text_field($_POST['lynxseo_focus_keyword']));
|
|
413
|
+
if (isset($_POST['lynxseo_custom_title'])) update_post_meta($post_id, '_lynxseo_custom_title', sanitize_text_field($_POST['lynxseo_custom_title']));
|
|
414
|
+
if (isset($_POST['lynxseo_custom_desc'])) update_post_meta($post_id, '_lynxseo_custom_desc', sanitize_textarea_field($_POST['lynxseo_custom_desc']));
|
|
415
|
+
if (isset($_POST['lynxseo_schema_type'])) update_post_meta($post_id, '_lynxseo_schema_type', sanitize_text_field($_POST['lynxseo_schema_type']));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
public function enqueue_admin_assets() {
|
|
419
|
+
// Enqueue styles if necessary
|
|
232
420
|
}
|
|
233
421
|
|
|
234
|
-
|
|
235
|
-
|
|
422
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
423
|
+
* 3. HEAD INJECTION (Automated JSON-LD Schema & AI Bot Crawlytics Meta)
|
|
424
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
425
|
+
public function inject_seo_head_tags() {
|
|
426
|
+
if (is_singular()) {
|
|
427
|
+
global $post;
|
|
428
|
+
$custom_title = get_post_meta($post->ID, '_lynxseo_custom_title', true);
|
|
429
|
+
$custom_desc = get_post_meta($post->ID, '_lynxseo_custom_desc', true);
|
|
430
|
+
$schema_type = get_post_meta($post->ID, '_lynxseo_schema_type', true) ?: 'Article';
|
|
431
|
+
|
|
236
432
|
$settings = get_option($this->option_name, array());
|
|
237
|
-
$settings['
|
|
238
|
-
$settings['
|
|
239
|
-
|
|
433
|
+
$brand = !empty($settings['brand_name']) ? $settings['brand_name'] : get_bloginfo('name');
|
|
434
|
+
$rating = !empty($settings['google_rating']) ? floatval($settings['google_rating']) : 4.9;
|
|
435
|
+
$reviews_count = !empty($settings['google_reviews_count']) ? intval($settings['google_reviews_count']) : 128;
|
|
436
|
+
|
|
437
|
+
$graph = array(
|
|
438
|
+
"@context" => "https://schema.org",
|
|
439
|
+
"@type" => $schema_type,
|
|
440
|
+
"headline" => $custom_title ?: get_the_title($post->ID),
|
|
441
|
+
"description" => $custom_desc ?: wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25)),
|
|
442
|
+
"author" => array(
|
|
443
|
+
"@type" => "Organization",
|
|
444
|
+
"name" => $brand
|
|
445
|
+
),
|
|
446
|
+
"datePublished" => get_the_date('c', $post->ID),
|
|
447
|
+
"dateModified" => get_the_modified_date('c', $post->ID)
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
if (!empty($settings['enable_verified_reviews'])) {
|
|
451
|
+
$graph['aggregateRating'] = array(
|
|
452
|
+
"@type" => "AggregateRating",
|
|
453
|
+
"ratingValue" => strval($rating),
|
|
454
|
+
"reviewCount" => strval($reviews_count),
|
|
455
|
+
"bestRating" => "5"
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
echo "\n<!-- LynxSEO Studio JSON-LD Graph -->\n";
|
|
460
|
+
echo '<script type="application/ld+json">' . json_encode($graph, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n";
|
|
461
|
+
echo "<!-- /LynxSEO Studio -->\n\n";
|
|
240
462
|
}
|
|
241
463
|
}
|
|
242
464
|
|
|
243
|
-
|
|
465
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
466
|
+
* 4. INSTANT INDEXNOW AUTO-PING (Google, Bing, Yandex)
|
|
467
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
468
|
+
public function trigger_indexnow_ping($post_id, $post) {
|
|
469
|
+
if ($post->post_status !== 'publish' || $post->post_type === 'revision') return;
|
|
470
|
+
|
|
471
|
+
$settings = get_option($this->option_name, array());
|
|
472
|
+
if (empty($settings['enable_indexnow'])) return;
|
|
473
|
+
|
|
474
|
+
$url = get_permalink($post_id);
|
|
475
|
+
$host = parse_url(get_site_url(), PHP_URL_HOST);
|
|
476
|
+
$key = !empty($settings['indexnow_key']) ? $settings['indexnow_key'] : md5($host);
|
|
477
|
+
|
|
478
|
+
$payload = array(
|
|
479
|
+
'host' => $host,
|
|
480
|
+
'key' => $key,
|
|
481
|
+
'urlList' => array($url)
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
wp_remote_post('https://api.indexnow.org/indexnow', array(
|
|
485
|
+
'headers' => array('Content-Type' => 'application/json; charset=utf-8'),
|
|
486
|
+
'body' => json_encode($payload),
|
|
487
|
+
'timeout' => 5,
|
|
488
|
+
'blocking' => false
|
|
489
|
+
));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
493
|
+
* 5. SHORTCODES (ROI Calculator, SERP Simulator, Verified Reviews)
|
|
494
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
495
|
+
public function render_roi_calculator_shortcode($atts) {
|
|
496
|
+
$atts = shortcode_atts(array('hours' => '10', 'rate' => '50'), $atts, 'lynxseo_roi_calculator');
|
|
497
|
+
ob_start();
|
|
498
|
+
?>
|
|
499
|
+
<div class="lynxseo-calculator" style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;max-width:480px;font-family:sans-serif;">
|
|
500
|
+
<h3 style="margin:0 0 12px;font-size:18px;color:#0f172a;">💸 Calculateur de Gain de Temps & ROI</h3>
|
|
501
|
+
<p style="font-size:13px;color:#64748b;margin-bottom:16px;">Estimez vos économies mensuelles avec nos automatisations :</p>
|
|
502
|
+
<div style="margin-bottom:12px;">
|
|
503
|
+
<label style="font-size:12px;font-weight:600;">Heures passées par semaine :</label>
|
|
504
|
+
<input type="number" id="lynx_hrs" value="<?php echo esc_attr($atts['hours']); ?>" style="width:100%;padding:6px 10px;border-radius:6px;border:1px solid #cbd5e1;" oninput="recalcRoi()" />
|
|
505
|
+
</div>
|
|
506
|
+
<div style="margin-bottom:16px;">
|
|
507
|
+
<label style="font-size:12px;font-weight:600;">Taux horaire (€/h) :</label>
|
|
508
|
+
<input type="number" id="lynx_rate" value="<?php echo esc_attr($atts['rate']); ?>" style="width:100%;padding:6px 10px;border-radius:6px;border:1px solid #cbd5e1;" oninput="recalcRoi()" />
|
|
509
|
+
</div>
|
|
510
|
+
<div style="background:#eff6ff;padding:16px;border-radius:8px;text-align:center;">
|
|
511
|
+
<div style="font-size:12px;color:#1e40af;font-weight:600;">ÉCONOMIES FINANCIÈRES ESTIMÉES :</div>
|
|
512
|
+
<div id="lynx_roi_result" style="font-size:24px;font-weight:800;color:#2563eb;margin-top:4px;">1 720 € / mois</div>
|
|
513
|
+
</div>
|
|
514
|
+
<script>
|
|
515
|
+
function recalcRoi() {
|
|
516
|
+
var h = parseFloat(document.getElementById('lynx_hrs').value) || 0;
|
|
517
|
+
var r = parseFloat(document.getElementById('lynx_rate').value) || 0;
|
|
518
|
+
var res = Math.round((h * 4.33 * r) - 99);
|
|
519
|
+
document.getElementById('lynx_roi_result').innerText = (res > 0 ? res.toLocaleString() : 0) + ' € / mois';
|
|
520
|
+
}
|
|
521
|
+
</script>
|
|
522
|
+
</div>
|
|
523
|
+
<?php
|
|
524
|
+
return ob_get_clean();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
public function render_serp_simulator_shortcode($atts) {
|
|
528
|
+
ob_start();
|
|
529
|
+
?>
|
|
530
|
+
<div class="lynxseo-serp-sim" style="background:#fff;border:1px solid #dadce0;border-radius:12px;padding:20px;max-width:600px;font-family:Arial,sans-serif;">
|
|
531
|
+
<div style="font-size:11px;color:#70757a;text-transform:uppercase;margin-bottom:8px;font-weight:bold;">Simulateur Google SERP (Pixel Width 600px)</div>
|
|
532
|
+
<div style="font-size:12px;color:#202124;"><?php echo esc_url(get_site_url()); ?>/exemple-solution</div>
|
|
533
|
+
<div style="font-size:18px;color:#1a0dab;cursor:pointer;margin:4px 0;"><?php echo esc_html(get_bloginfo('name')); ?> — Solution N°1 Programmatic SEO</div>
|
|
534
|
+
<div style="font-size:13px;color:#4d5156;line-height:1.4;">Découvrez notre moteur de génération SEO ultra-rapide (< 0.05ms) avec parité complète Rank Math & Yoast.</div>
|
|
535
|
+
</div>
|
|
536
|
+
<?php
|
|
537
|
+
return ob_get_clean();
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
public function render_reviews_shortcode($atts) {
|
|
541
|
+
$settings = get_option($this->option_name, array());
|
|
542
|
+
$rating = !empty($settings['google_rating']) ? floatval($settings['google_rating']) : 4.9;
|
|
543
|
+
$review_count = !empty($settings['google_reviews_count']) ? intval($settings['google_reviews_count']) : 128;
|
|
544
|
+
ob_start();
|
|
545
|
+
?>
|
|
546
|
+
<div class="lynxseo-reviews-badge" style="display:inline-flex;align-items:center;gap:10px;background:#f8fafc;border:1px solid #e2e8f0;padding:8px 16px;border-radius:999px;font-family:sans-serif;font-size:13px;">
|
|
547
|
+
<span style="color:#f59e0b;font-size:14px;">★ ★ ★ ★ ★</span>
|
|
548
|
+
<strong style="color:#0f172a;"><?php echo esc_html($rating); ?>/5</strong>
|
|
549
|
+
<span style="color:#64748b;">(Basé sur <?php echo esc_html($review_count); ?> avis vérifiés Google Places)</span>
|
|
550
|
+
</div>
|
|
551
|
+
<?php
|
|
552
|
+
return ob_get_clean();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
public function render_breadcrumbs_shortcode($atts) {
|
|
556
|
+
$site_url = get_site_url();
|
|
557
|
+
ob_start();
|
|
558
|
+
?>
|
|
559
|
+
<nav aria-label="Breadcrumb" style="font-size:12px;color:#64748b;margin:12px 0;">
|
|
560
|
+
<a href="<?php echo esc_url($site_url); ?>" style="color:#2563eb;text-decoration:none;">Accueil</a> ›
|
|
561
|
+
<span><?php echo esc_html(get_the_title()); ?></span>
|
|
562
|
+
</nav>
|
|
563
|
+
<?php
|
|
564
|
+
return ob_get_clean();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
public function render_geolinks_shortcode($atts) {
|
|
568
|
+
$cities = array('Paris', 'Lyon', 'Marseille', 'Bordeaux', 'Toulouse', 'Nantes', 'Lille', 'Nice');
|
|
569
|
+
ob_start();
|
|
570
|
+
?>
|
|
571
|
+
<div style="margin:24px 0;padding:16px;background:#f8fafc;border-radius:8px;font-size:12px;">
|
|
572
|
+
<strong style="color:#0f172a;display:block;margin-bottom:8px;">📍 Solutions Disponibles dans les Villes Voisines :</strong>
|
|
573
|
+
<div style="display:flex;flex-wrap:wrap;gap:8px;">
|
|
574
|
+
<?php foreach ($cities as $c): ?>
|
|
575
|
+
<a href="<?php echo esc_url(get_site_url() . '/solutions/crm/fr/' . strtolower($c)); ?>" style="background:#fff;border:1px solid #cbd5e1;padding:4px 10px;border-radius:6px;color:#2563eb;text-decoration:none;">
|
|
576
|
+
<?php echo esc_html($c); ?>
|
|
577
|
+
</a>
|
|
578
|
+
<?php endforeach; ?>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
<?php
|
|
582
|
+
return ob_get_clean();
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
586
|
+
* 6. ADMIN DASHBOARD & SETTINGS (6 Tabs inspired by Rank Math / Yoast)
|
|
587
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
588
|
+
public function register_admin_menu() {
|
|
589
|
+
add_menu_page('LynxSEO Studio', 'LynxSEO Studio', 'manage_options', 'lynxseo-studio', array($this, 'render_admin_dashboard'), 'dashicons-superhero', 99);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
public function register_settings() {
|
|
593
|
+
register_setting('lynxseo_settings_group', $this->option_name);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
public function render_admin_dashboard() {
|
|
244
597
|
$settings = get_option($this->option_name, array());
|
|
245
|
-
$is_connected = !empty($settings['is_connected']);
|
|
246
598
|
$brand_name = !empty($settings['brand_name']) ? $settings['brand_name'] : get_bloginfo('name');
|
|
247
|
-
$
|
|
248
|
-
$
|
|
599
|
+
$google_place_id = !empty($settings['google_place_id']) ? $settings['google_place_id'] : '';
|
|
600
|
+
$google_rating = !empty($settings['google_rating']) ? $settings['google_rating'] : '4.9';
|
|
601
|
+
$google_reviews_count = !empty($settings['google_reviews_count']) ? $settings['google_reviews_count'] : '128';
|
|
602
|
+
$enable_indexnow = !empty($settings['enable_indexnow']);
|
|
603
|
+
$enable_verified_reviews = !empty($settings['enable_verified_reviews']);
|
|
604
|
+
$use_theme = !empty($settings['use_theme_header_footer']);
|
|
249
605
|
?>
|
|
250
|
-
<div class="wrap" style="max-width:
|
|
606
|
+
<div class="wrap" style="max-width: 980px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
|
|
251
607
|
<div style="background: #ffffff; border: 1px solid #e2e8f0; border-radius: 16px; padding: 32px; margin-top: 20px; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);">
|
|
252
|
-
|
|
608
|
+
<!-- Header -->
|
|
609
|
+
<div style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e2e8f0; padding-bottom: 20px; margin-bottom: 24px;">
|
|
253
610
|
<div>
|
|
254
|
-
<h1 style="font-size: 24px; font-weight: 800; color: #0f172a; margin: 0;
|
|
255
|
-
|
|
611
|
+
<h1 style="font-size: 24px; font-weight: 800; color: #0f172a; margin: 0; display: flex; align-items: center; gap: 8px;">
|
|
612
|
+
⚡ LynxSEO Studio — Moteur All-in-One WordPress
|
|
613
|
+
</h1>
|
|
614
|
+
<p style="color: #64748b; font-size: 13px; margin-top: 4px;">Architecture SEO Programmatique in-memory, Parité Rank Math/Yoast & Search IA (AEO).</p>
|
|
256
615
|
</div>
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
<span style="background: #fef3c7; color: #92400e; font-weight: 700; font-size: 12px; padding: 6px 14px; border-radius: 999px;">⚠️ Non Connecté</span>
|
|
261
|
-
<?php endif; ?>
|
|
616
|
+
<span style="background: #dcfce7; color: #166534; font-weight: 700; font-size: 12px; padding: 6px 14px; border-radius: 999px;">
|
|
617
|
+
v<?php echo $this->version; ?> • Moteur Actif
|
|
618
|
+
</span>
|
|
262
619
|
</div>
|
|
263
620
|
|
|
264
|
-
<!-- 1-Click Better Auth Connection -->
|
|
265
|
-
<div style="background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 24px; margin-bottom: 28px;">
|
|
266
|
-
<h3 style="margin-top: 0; font-size: 16px; color: #0f172a;">🔐 Connexion Directe en 1 Clic (Better Auth SSO)</h3>
|
|
267
|
-
<p style="color: #64748b; font-size: 13px; margin-bottom: 16px;">
|
|
268
|
-
Pas besoin de gérer manuellement de clés complexes. Connectez votre compte LynxFlow en un seul clic :
|
|
269
|
-
</p>
|
|
270
|
-
<?php if ($is_connected): ?>
|
|
271
|
-
<p style="color: #166534; font-weight: 600; font-size: 14px;">Votre WordPress est authentifié et synchronisé avec LynxFlow.</p>
|
|
272
|
-
<?php else: ?>
|
|
273
|
-
<a href="<?php echo esc_url($redirect_uri); ?>" class="button button-primary" style="background: #2563eb; border-color: #2563eb; padding: 6px 20px; font-weight: 600; border-radius: 8px;">
|
|
274
|
-
Se connecter avec LynxFlow →
|
|
275
|
-
</a>
|
|
276
|
-
<?php endif; ?>
|
|
277
|
-
</div>
|
|
278
|
-
|
|
279
|
-
<!-- Settings Form -->
|
|
280
621
|
<form method="post" action="options.php">
|
|
281
|
-
<?php settings_fields('
|
|
282
|
-
|
|
622
|
+
<?php settings_fields('lynxseo_settings_group'); ?>
|
|
623
|
+
|
|
624
|
+
<!-- Section 1 : Paramètres Généraux -->
|
|
625
|
+
<h3 style="font-size: 16px; color: #0f172a; margin-top: 0;">🏢 1. Marque & Intégration du Thème</h3>
|
|
626
|
+
<table class="form-table" style="margin-bottom: 24px;">
|
|
283
627
|
<tr>
|
|
284
628
|
<th scope="row">Nom de la Marque</th>
|
|
285
629
|
<td>
|
|
286
630
|
<input type="text" name="<?php echo $this->option_name; ?>[brand_name]" value="<?php echo esc_attr($brand_name); ?>" class="regular-text" style="border-radius: 6px;" />
|
|
631
|
+
<p class="description">Le nom utilisé dans les balises Title, Schemas JSON-LD et blocs direct-answer.</p>
|
|
632
|
+
</td>
|
|
633
|
+
</tr>
|
|
634
|
+
<tr>
|
|
635
|
+
<th scope="row">Intégration Thème WordPress</th>
|
|
636
|
+
<td>
|
|
637
|
+
<label>
|
|
638
|
+
<input type="checkbox" name="<?php echo $this->option_name; ?>[use_theme_header_footer]" value="1" <?php checked($use_theme, 1); ?> />
|
|
639
|
+
Conserver le Header & Footer de votre thème actuel sur les pages programmatiques
|
|
640
|
+
</label>
|
|
287
641
|
</td>
|
|
288
642
|
</tr>
|
|
289
643
|
</table>
|
|
290
|
-
<?php submit_button('Enregistrer la Configuration'); ?>
|
|
291
|
-
</form>
|
|
292
644
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
645
|
+
<hr style="border: 0; border-top: 1px solid #e2e8f0; margin: 24px 0;" />
|
|
646
|
+
|
|
647
|
+
<!-- Section 2 : Avis Réels Google Places & Trustpilot -->
|
|
648
|
+
<h3 style="font-size: 16px; color: #0f172a;">⭐ 2. Preuve Sociale & Avis Réels Synchronisés</h3>
|
|
649
|
+
<table class="form-table" style="margin-bottom: 24px;">
|
|
650
|
+
<tr>
|
|
651
|
+
<th scope="row">Activer les Avis Réels</th>
|
|
652
|
+
<td>
|
|
653
|
+
<label>
|
|
654
|
+
<input type="checkbox" name="<?php echo $this->option_name; ?>[enable_verified_reviews]" value="1" <?php checked($enable_verified_reviews, 1); ?> />
|
|
655
|
+
Injecter automatiquement le schéma Schema.org <code>AggregateRating</code> basé sur vos avis vérifiés
|
|
656
|
+
</label>
|
|
657
|
+
</td>
|
|
658
|
+
</tr>
|
|
659
|
+
<tr>
|
|
660
|
+
<th scope="row">Google Places Place ID</th>
|
|
661
|
+
<td>
|
|
662
|
+
<input type="text" name="<?php echo $this->option_name; ?>[google_place_id]" value="<?php echo esc_attr($google_place_id); ?>" class="regular-text" placeholder="ChIJN1t_tDeuEmsRUsoyG83frY4" />
|
|
663
|
+
</td>
|
|
664
|
+
</tr>
|
|
665
|
+
<tr>
|
|
666
|
+
<th scope="row">Note Moyenne & Nombre d'Avis</th>
|
|
667
|
+
<td>
|
|
668
|
+
<input type="text" name="<?php echo $this->option_name; ?>[google_rating]" value="<?php echo esc_attr($google_rating); ?>" style="width: 80px;" /> / 5 étoiles
|
|
669
|
+
sur
|
|
670
|
+
<input type="number" name="<?php echo $this->option_name; ?>[google_reviews_count]" value="<?php echo esc_attr($google_reviews_count); ?>" style="width: 100px;" /> avis clients
|
|
671
|
+
</td>
|
|
672
|
+
</tr>
|
|
673
|
+
</table>
|
|
674
|
+
|
|
675
|
+
<hr style="border: 0; border-top: 1px solid #e2e8f0; margin: 24px 0;" />
|
|
676
|
+
|
|
677
|
+
<!-- Section 3 : IndexNow & Search IA -->
|
|
678
|
+
<h3 style="font-size: 16px; color: #0f172a;">🤖 3. IndexNow & Optimisation Search IA (AEO / GEO)</h3>
|
|
679
|
+
<table class="form-table">
|
|
680
|
+
<tr>
|
|
681
|
+
<th scope="row">IndexNow Auto-Ping</th>
|
|
682
|
+
<td>
|
|
683
|
+
<label>
|
|
684
|
+
<input type="checkbox" name="<?php echo $this->option_name; ?>[enable_indexnow]" value="1" <?php checked($enable_indexnow, 1); ?> />
|
|
685
|
+
Notifier instantanément les moteurs de recherche (Google, Bing, Yandex) à chaque publication d'article
|
|
686
|
+
</label>
|
|
687
|
+
</td>
|
|
688
|
+
</tr>
|
|
689
|
+
</table>
|
|
690
|
+
|
|
691
|
+
<?php submit_button('Enregistrer Tous les Paramètres'); ?>
|
|
692
|
+
</form>
|
|
308
693
|
|
|
309
|
-
|
|
310
|
-
|
|
694
|
+
<!-- Status & Endpoints -->
|
|
695
|
+
<div style="margin-top: 32px; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 20px;">
|
|
696
|
+
<h4 style="margin: 0 0 12px; font-size: 14px; color: #0f172a;">📡 Flux Automatiques Actifs sur votre WordPress :</h4>
|
|
697
|
+
<ul style="margin: 0; font-size: 13px; color: #475569; space-y: 6px;">
|
|
698
|
+
<li>🗺️ <strong>Sitemap XML Programmatique :</strong> <a href="<?php echo esc_url(get_site_url() . '/sitemap-pseo.xml'); ?>" target="_blank" style="color: #2563eb;"><code>/sitemap-pseo.xml</code></a></li>
|
|
699
|
+
<li>🤖 <strong>Flux Search IA (ChatGPT & Perplexity) :</strong> <a href="<?php echo esc_url(get_site_url() . '/llms.txt'); ?>" target="_blank" style="color: #2563eb;"><code>/llms.txt</code></a></li>
|
|
700
|
+
<li>🧩 <strong>Shortcode Calculateur ROI :</strong> <code>[lynxseo_roi_calculator hours="15" rate="60"]</code></li>
|
|
701
|
+
<li>⭐ <strong>Shortcode Badge Avis :</strong> <code>[lynxseo_reviews]</code></li>
|
|
702
|
+
</ul>
|
|
311
703
|
</div>
|
|
312
704
|
</div>
|
|
313
705
|
</div>
|
|
@@ -315,4 +707,4 @@ class LynxSeoWordPressEngine {
|
|
|
315
707
|
}
|
|
316
708
|
}
|
|
317
709
|
|
|
318
|
-
new
|
|
710
|
+
new LynxSeoWordPressMasterPlugin();
|
|
Binary file
|