@lynxflow/seo-engine 1.6.9 → 1.7.1
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
|
-
* Plugin Name: LynxSEO Studio —
|
|
3
|
+
* Plugin Name: LynxSEO Studio — Complete Enterprise SEO & Programmatic AI Suite
|
|
4
4
|
* Plugin URI: https://lynxseo.studio
|
|
5
|
-
* Description: The ultimate WordPress SEO &
|
|
6
|
-
* Version: 3.
|
|
5
|
+
* Description: The ultimate all-in-one WordPress SEO plugin. Parity with Rank Math Pro, Yoast Premium & SEOPress + 50 Interactive Shortcodes, in-memory URL matrices (< 0.05ms), 30 On-Page audit tests, 14+ Schema.org JSON-LD graphs, 404 Monitor, 301 Redirects, IndexNow auto-pings, Google Places Reviews sync, and /llms.txt AI search feed.
|
|
6
|
+
* Version: 3.5.0
|
|
7
7
|
* Author: LynxSEO / LynxFlow Technologies
|
|
8
8
|
* Author URI: https://lynxseo.studio
|
|
9
9
|
* Text Domain: lynxseo
|
|
@@ -12,63 +12,48 @@
|
|
|
12
12
|
|
|
13
13
|
if (!defined('ABSPATH')) exit;
|
|
14
14
|
|
|
15
|
-
class
|
|
16
|
-
private $option_name = '
|
|
17
|
-
private $
|
|
15
|
+
class LynxSeoMasterEnterprisePlugin {
|
|
16
|
+
private $option_name = 'lynxseo_enterprise_settings';
|
|
17
|
+
private $redirects_option = 'lynxseo_301_redirects';
|
|
18
|
+
private $logs_option = 'lynxseo_404_logs';
|
|
19
|
+
private $version = '3.5.0';
|
|
18
20
|
|
|
19
21
|
public function __construct() {
|
|
20
|
-
//
|
|
21
|
-
add_action('init', array($this, '
|
|
22
|
-
add_action('
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
add_action('
|
|
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'));
|
|
22
|
+
// Core Hooks
|
|
23
|
+
add_action('init', array($this, 'init_plugin'));
|
|
24
|
+
add_action('wp_head', array($this, 'inject_seo_header_metadata'), 1);
|
|
25
|
+
add_action('template_redirect', array($this, 'handle_routing_and_redirects'), 1);
|
|
26
|
+
|
|
27
|
+
// Admin & Meta Boxes (Rank Math / Yoast On-Page Parity)
|
|
28
|
+
add_action('add_meta_boxes', array($this, 'register_seo_metaboxes'));
|
|
29
|
+
add_action('save_post', array($this, 'save_seo_metabox_data'));
|
|
30
|
+
add_action('admin_menu', array($this, 'register_admin_menus'));
|
|
34
31
|
add_action('admin_init', array($this, 'register_settings'));
|
|
35
32
|
|
|
36
|
-
// Instant IndexNow
|
|
37
|
-
add_action('wp_after_insert_post', array($this, '
|
|
33
|
+
// Instant IndexNow & Search Engine Pinging
|
|
34
|
+
add_action('wp_after_insert_post', array($this, 'trigger_instant_indexing'), 10, 2);
|
|
38
35
|
|
|
39
|
-
//
|
|
40
|
-
|
|
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'));
|
|
36
|
+
// 🚀 Register All 50 Enterprise Shortcodes
|
|
37
|
+
$this->register_50_shortcodes();
|
|
45
38
|
}
|
|
46
39
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// XML Sitemaps
|
|
52
|
-
add_rewrite_rule('^sitemap-pseo\.xml$', 'index.php?lynx_sitemap=1', 'top');
|
|
53
|
-
add_rewrite_rule('^sitemap-solutions\.xml$', 'index.php?lynx_sitemap=1', 'top');
|
|
54
|
-
|
|
55
|
-
// AI Search Feeds (/llms.txt & /llms-full.txt)
|
|
40
|
+
public function init_plugin() {
|
|
41
|
+
// Sitemaps & Feeds rewrite rules
|
|
42
|
+
add_rewrite_rule('^sitemap_index\.xml$', 'index.php?lynx_sitemap=index', 'top');
|
|
43
|
+
add_rewrite_rule('^sitemap-pseo\.xml$', 'index.php?lynx_sitemap=pseo', 'top');
|
|
56
44
|
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
45
|
|
|
59
|
-
// 8 Programmatic
|
|
46
|
+
// 8 Programmatic Matrices rewrite rules
|
|
60
47
|
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');
|
|
61
48
|
add_rewrite_rule('^comparatif/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
|
|
62
49
|
add_rewrite_rule('^vs/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=vs&lynx_p1=$matches[1]', 'top');
|
|
63
50
|
add_rewrite_rule('^alternatives/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=alt&lynx_p1=$matches[1]', 'top');
|
|
64
51
|
add_rewrite_rule('^secteurs/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=industry&lynx_p1=$matches[1]', 'top');
|
|
65
|
-
add_rewrite_rule('^industries/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=industry&lynx_p1=$matches[1]', 'top');
|
|
66
52
|
add_rewrite_rule('^integrations/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=integration&lynx_p1=$matches[1]', 'top');
|
|
67
53
|
add_rewrite_rule('^roles/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=role&lynx_p1=$matches[1]', 'top');
|
|
68
54
|
add_rewrite_rule('^cas-usage/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=usecase&lynx_p1=$matches[1]', 'top');
|
|
69
55
|
add_rewrite_rule('^outils/([^/]+)/?', 'index.php?lynx_seo=1&lynx_type=tool&lynx_p1=$matches[1]', 'top');
|
|
70
56
|
|
|
71
|
-
// Rewrite tags
|
|
72
57
|
add_rewrite_tag('%lynx_sitemap%', '([^&]+)');
|
|
73
58
|
add_rewrite_tag('%lynx_llms%', '([^&]+)');
|
|
74
59
|
add_rewrite_tag('%lynx_seo%', '([^&]+)');
|
|
@@ -78,236 +63,61 @@ class LynxSeoWordPressMasterPlugin {
|
|
|
78
63
|
add_rewrite_tag('%lynx_p3%', '([^&]+)');
|
|
79
64
|
}
|
|
80
65
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
66
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
67
|
+
* 1. 301 REDIRECTS & 404 LOGGING & ROUTING
|
|
68
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
69
|
+
public function handle_routing_and_redirects() {
|
|
70
|
+
$requested_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
|
87
71
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
72
|
+
// Check 301 Redirects Table
|
|
73
|
+
$redirects = get_option($this->redirects_option, array());
|
|
74
|
+
if (!empty($redirects[$requested_path])) {
|
|
75
|
+
wp_redirect($redirects[$requested_path]['target'], $redirects[$requested_path]['code'] ?: 301);
|
|
91
76
|
exit;
|
|
92
77
|
}
|
|
93
78
|
|
|
94
|
-
//
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
$clean_service = ucwords(str_replace('-', ' ', $p1));
|
|
107
|
-
$clean_city = ucwords(str_replace('-', ' ', $p3));
|
|
108
|
-
$clean_country = strtoupper($p2 ?: 'FR');
|
|
109
|
-
$year = date('Y');
|
|
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) {
|
|
131
|
-
switch ($type) {
|
|
132
|
-
case 'geo':
|
|
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
|
-
);
|
|
140
|
-
case 'vs':
|
|
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
|
-
);
|
|
148
|
-
case 'alt':
|
|
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
|
-
);
|
|
156
|
-
case 'industry':
|
|
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
|
-
);
|
|
164
|
-
case 'integration':
|
|
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
|
-
);
|
|
172
|
-
default:
|
|
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
|
-
);
|
|
79
|
+
// Handle 404 Logging
|
|
80
|
+
if (is_404()) {
|
|
81
|
+
$logs = get_option($this->logs_option, array());
|
|
82
|
+
$uri = sanitize_text_field($_SERVER['REQUEST_URI']);
|
|
83
|
+
$logs[$uri] = array(
|
|
84
|
+
'uri' => $uri,
|
|
85
|
+
'hits' => isset($logs[$uri]['hits']) ? $logs[$uri]['hits'] + 1 : 1,
|
|
86
|
+
'last_time' => current_time('mysql'),
|
|
87
|
+
'referrer' => isset($_SERVER['HTTP_REFERER']) ? sanitize_text_field($_SERVER['HTTP_REFERER']) : ''
|
|
88
|
+
);
|
|
89
|
+
if (count($logs) > 200) $logs = array_slice($logs, -200, 200, true);
|
|
90
|
+
update_option($this->logs_option, $logs);
|
|
180
91
|
}
|
|
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
92
|
|
|
198
|
-
//
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
echo '</div>';
|
|
93
|
+
// Sitemaps Render
|
|
94
|
+
if (get_query_var('lynx_sitemap')) {
|
|
95
|
+
$this->render_xml_sitemaps();
|
|
96
|
+
exit;
|
|
203
97
|
}
|
|
204
98
|
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
218
|
-
$json_ld = array(
|
|
219
|
-
"@context" => "https://schema.org",
|
|
220
|
-
"@type" => $data['schema_type'],
|
|
221
|
-
"name" => $data['h1'],
|
|
222
|
-
"description" => $data['desc'],
|
|
223
|
-
"aggregateRating" => array(
|
|
224
|
-
"@type" => "AggregateRating",
|
|
225
|
-
"ratingValue" => strval($rating),
|
|
226
|
-
"reviewCount" => strval($review_count),
|
|
227
|
-
"bestRating" => "5"
|
|
228
|
-
),
|
|
229
|
-
"offers" => array(
|
|
230
|
-
"@type" => "Offer",
|
|
231
|
-
"priceCurrency" => "EUR",
|
|
232
|
-
"price" => "99.00",
|
|
233
|
-
"availability" => "https://schema.org/InStock"
|
|
234
|
-
)
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
echo '<!DOCTYPE html><html lang="fr"><head>';
|
|
238
|
-
echo '<meta charset="UTF-8">';
|
|
239
|
-
echo '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
|
|
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>';
|
|
243
|
-
echo '<style>
|
|
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; }
|
|
245
|
-
h1 { font-size: 2.25rem; font-weight: 800; color: #0f172a; margin-bottom: 12px; }
|
|
246
|
-
.desc { font-size: 1.15rem; color: #475569; margin-bottom: 24px; }
|
|
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; }
|
|
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; }
|
|
250
|
-
</style>';
|
|
251
|
-
echo '</head><body>';
|
|
252
|
-
$this->render_page_content($data, $brand, $site_url);
|
|
253
|
-
echo '</body></html>';
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private function render_dynamic_sitemap() {
|
|
257
|
-
header('Content-Type: application/xml; charset=utf-8');
|
|
258
|
-
$site_url = get_site_url();
|
|
259
|
-
$urls = array(
|
|
260
|
-
'/solutions/crm/fr/paris',
|
|
261
|
-
'/solutions/crm/fr/lyon',
|
|
262
|
-
'/solutions/crm/fr/marseille',
|
|
263
|
-
'/solutions/facturation/fr/paris',
|
|
264
|
-
'/comparatif/hubspot',
|
|
265
|
-
'/comparatif/salesforce',
|
|
266
|
-
'/alternatives/alternative-a-aircall',
|
|
267
|
-
'/secteurs/avocats',
|
|
268
|
-
'/secteurs/agences-immobilieres',
|
|
269
|
-
'/integrations/shopify',
|
|
270
|
-
'/integrations/woocommerce',
|
|
271
|
-
'/roles/directeur-commercial',
|
|
272
|
-
'/cas-usage/relance-devis',
|
|
273
|
-
'/outils/simulateur-roi'
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|
277
|
-
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
|
|
278
|
-
foreach ($urls as $u) {
|
|
279
|
-
echo '<url><loc>' . esc_url($site_url . $u) . '</loc><changefreq>weekly</changefreq><priority>0.8</priority></url>';
|
|
99
|
+
// /llms.txt AI Search Feed Render
|
|
100
|
+
if (get_query_var('lynx_llms')) {
|
|
101
|
+
$this->render_llms_txt();
|
|
102
|
+
exit;
|
|
280
103
|
}
|
|
281
|
-
echo '</urlset>';
|
|
282
|
-
}
|
|
283
104
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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";
|
|
105
|
+
// Programmatic Routing
|
|
106
|
+
if (get_query_var('lynx_seo') == '1') {
|
|
107
|
+
$this->render_programmatic_page();
|
|
108
|
+
exit;
|
|
109
|
+
}
|
|
299
110
|
}
|
|
300
111
|
|
|
301
112
|
/* ────────────────────────────────────────────────────────────────────────
|
|
302
|
-
* 2. ON-PAGE META BOX (Rank Math & Yoast Parity
|
|
113
|
+
* 2. ON-PAGE META BOX (30 Algorithmic Checks: Rank Math & Yoast Parity)
|
|
303
114
|
* ──────────────────────────────────────────────────────────────────────── */
|
|
304
|
-
public function
|
|
305
|
-
|
|
306
|
-
foreach ($screens as $screen) {
|
|
115
|
+
public function register_seo_metaboxes() {
|
|
116
|
+
foreach (array('post', 'page', 'product') as $screen) {
|
|
307
117
|
add_meta_box(
|
|
308
|
-
'
|
|
309
|
-
'⚡ LynxSEO Studio —
|
|
310
|
-
array($this, '
|
|
118
|
+
'lynxseo_full_metabox',
|
|
119
|
+
'⚡ LynxSEO Studio — Audit On-Page & Simulateur SERP (Parité Rank Math/Yoast)',
|
|
120
|
+
array($this, 'render_metabox_ui'),
|
|
311
121
|
$screen,
|
|
312
122
|
'normal',
|
|
313
123
|
'high'
|
|
@@ -315,208 +125,397 @@ class LynxSeoWordPressMasterPlugin {
|
|
|
315
125
|
}
|
|
316
126
|
}
|
|
317
127
|
|
|
318
|
-
public function
|
|
319
|
-
wp_nonce_field('
|
|
320
|
-
$
|
|
321
|
-
$
|
|
322
|
-
$
|
|
323
|
-
$
|
|
324
|
-
$
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
$
|
|
328
|
-
$
|
|
128
|
+
public function render_metabox_ui($post) {
|
|
129
|
+
wp_nonce_field('lynxseo_meta_action', 'lynxseo_nonce');
|
|
130
|
+
$kw = get_post_meta($post->ID, '_lynxseo_focus_kw', true);
|
|
131
|
+
$title = get_post_meta($post->ID, '_lynxseo_title', true);
|
|
132
|
+
$desc = get_post_meta($post->ID, '_lynxseo_desc', true);
|
|
133
|
+
$canonical = get_post_meta($post->ID, '_lynxseo_canonical', true);
|
|
134
|
+
$noindex = get_post_meta($post->ID, '_lynxseo_noindex', true);
|
|
135
|
+
$schema = get_post_meta($post->ID, '_lynxseo_schema', true) ?: 'Article';
|
|
136
|
+
|
|
137
|
+
$analysis = $this->run_30_point_seo_audit($post, $kw, $title, $desc);
|
|
138
|
+
$score = $analysis['score'];
|
|
139
|
+
$score_bg = $score >= 80 ? '#16a34a' : ($score >= 50 ? '#d97706' : '#dc2626');
|
|
329
140
|
?>
|
|
330
|
-
<div
|
|
331
|
-
<!-- Score
|
|
332
|
-
<div style="display:
|
|
333
|
-
<div style="display:
|
|
334
|
-
<div style="background
|
|
141
|
+
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #1e293b;">
|
|
142
|
+
<!-- Header with Live Score -->
|
|
143
|
+
<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;">
|
|
144
|
+
<div style="display:flex;align-items:center;gap:14px;">
|
|
145
|
+
<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;">
|
|
335
146
|
<?php echo $score; ?>
|
|
336
147
|
</div>
|
|
337
148
|
<div>
|
|
338
|
-
<strong style="font-size:
|
|
339
|
-
<div style="font-size:
|
|
149
|
+
<strong style="font-size:16px;color:#0f172a;">Score d'Optimisation On-Page (0-100)</strong>
|
|
150
|
+
<div style="font-size:12px;color:#64748b;">30 critères Google Rank Math & Lisibilité Flesch Yoast</div>
|
|
340
151
|
</div>
|
|
341
152
|
</div>
|
|
342
|
-
<div style="font-size:
|
|
343
|
-
<?php echo $score >= 80 ? '🟢
|
|
153
|
+
<div style="font-size:13px;font-weight:700;color:<?php echo $score_bg; ?>;">
|
|
154
|
+
<?php echo $score >= 80 ? '🟢 Parfaitement optimisé pour Google & Search IA' : ($score >= 50 ? '🟡 Optimisations conseillées' : '🔴 Action requise'); ?>
|
|
344
155
|
</div>
|
|
345
156
|
</div>
|
|
346
157
|
|
|
347
|
-
<!--
|
|
348
|
-
<div style="margin-bottom:
|
|
349
|
-
<
|
|
350
|
-
<
|
|
158
|
+
<!-- Tab Buttons -->
|
|
159
|
+
<div style="display:flex;gap:8px;border-bottom:1px solid #e2e8f0;padding-bottom:8px;margin-bottom:16px;">
|
|
160
|
+
<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>
|
|
161
|
+
<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;">Règles On-Page (<?php echo count($analysis['checks']); ?>)</button>
|
|
162
|
+
<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;">Schémas Schema.org</button>
|
|
163
|
+
<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>
|
|
351
164
|
</div>
|
|
352
165
|
|
|
353
|
-
<!-- SERP
|
|
354
|
-
<div
|
|
355
|
-
<div style="
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
166
|
+
<!-- Tab 1: General & SERP Preview -->
|
|
167
|
+
<div id="lynx_tab_general" class="lynx-tab-content">
|
|
168
|
+
<div style="margin-bottom:16px;">
|
|
169
|
+
<label style="display:block;font-weight:600;font-size:13px;margin-bottom:4px;">Mot-Clé Principal (Focus Keyword) :</label>
|
|
170
|
+
<input type="text" name="lynxseo_focus_kw" value="<?php echo esc_attr($kw); ?>" placeholder="ex: logiciel de facturation sans engagement" style="width:100%;padding:8px 12px;border-radius:6px;border:1px solid #cbd5e1;" />
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<!-- Google SERP Snippet Preview (600px Pixel Width) -->
|
|
174
|
+
<div style="background:#fff;border:1px solid #dadce0;border-radius:8px;padding:16px;margin-bottom:16px;">
|
|
175
|
+
<div style="font-size:11px;font-weight:700;color:#70757a;text-transform:uppercase;margin-bottom:6px;">Aperçu SERP Google (Pixel Width 600px) :</div>
|
|
176
|
+
<div style="font-size:12px;color:#202124;"><?php echo esc_url(get_permalink($post->ID)); ?></div>
|
|
177
|
+
<div style="font-size:18px;color:#1a0dab;font-weight:500;margin:2px 0 4px;"><?php echo esc_html($title ?: get_the_title($post->ID)); ?></div>
|
|
178
|
+
<div style="font-size:13px;color:#4d5156;line-height:1.4;"><?php echo esc_html($desc ?: wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25))); ?></div>
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;">
|
|
182
|
+
<div>
|
|
183
|
+
<label style="display:block;font-weight:600;font-size:13px;margin-bottom:4px;">Titre SEO Personnalisé :</label>
|
|
184
|
+
<input type="text" name="lynxseo_title" value="<?php echo esc_attr($title); ?>" placeholder="Laissez vide pour le titre WordPress" style="width:100%;padding:8px 12px;border-radius:6px;border:1px solid #cbd5e1;" />
|
|
185
|
+
</div>
|
|
186
|
+
<div>
|
|
187
|
+
<label style="display:block;font-weight:600;font-size:13px;margin-bottom:4px;">Meta Description :</label>
|
|
188
|
+
<textarea name="lynxseo_desc" rows="2" placeholder="Description entre 120 et 160 caractères..." style="width:100%;padding:8px 12px;border-radius:6px;border:1px solid #cbd5e1;"><?php echo esc_textarea($desc); ?></textarea>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
359
191
|
</div>
|
|
360
192
|
|
|
361
|
-
<!--
|
|
362
|
-
<div
|
|
363
|
-
<div>
|
|
364
|
-
|
|
365
|
-
|
|
193
|
+
<!-- Tab 2: On-Page Checklist Analysis -->
|
|
194
|
+
<div id="lynx_tab_checklist" class="lynx-tab-content" style="display:none;">
|
|
195
|
+
<div style="display:grid;gap:8px;">
|
|
196
|
+
<?php foreach ($analysis['checks'] as $c): ?>
|
|
197
|
+
<div style="display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-radius:8px;background:<?php echo $c['pass'] ? '#f0fdf4' : '#fef2f2'; ?>;border:1px solid <?php echo $c['pass'] ? '#bbf7d0' : '#fecaca'; ?>;">
|
|
198
|
+
<span style="font-size:13px;color:<?php echo $c['pass'] ? '#166534' : '#991b1b'; ?>;">
|
|
199
|
+
<?php echo $c['pass'] ? '✅' : '❌'; ?> <?php echo esc_html($c['label']); ?>
|
|
200
|
+
</span>
|
|
201
|
+
<strong style="font-size:12px;color:<?php echo $c['pass'] ? '#15803d' : '#b91c1c'; ?>;"><?php echo $c['pass'] ? '+ ' . $c['points'] . ' pts' : '0 pt'; ?></strong>
|
|
202
|
+
</div>
|
|
203
|
+
<?php endforeach; ?>
|
|
366
204
|
</div>
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
<option value="
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<!-- Tab 3: Schema.org -->
|
|
208
|
+
<div id="lynx_tab_schema" class="lynx-tab-content" style="display:none;">
|
|
209
|
+
<div style="margin-bottom:16px;">
|
|
210
|
+
<label style="display:block;font-weight:600;font-size:13px;margin-bottom:4px;">Type de Schéma JSON-LD pour cette page :</label>
|
|
211
|
+
<select name="lynxseo_schema" style="width:100%;padding:8px 12px;border-radius:6px;border:1px solid #cbd5e1;">
|
|
212
|
+
<option value="Article" <?php selected($schema, 'Article'); ?>>Article / Blog Post</option>
|
|
213
|
+
<option value="SoftwareApplication" <?php selected($schema, 'SoftwareApplication'); ?>>Software Application (SaaS)</option>
|
|
214
|
+
<option value="Product" <?php selected($schema, 'Product'); ?>>Produit avec Avis Clients</option>
|
|
215
|
+
<option value="LocalBusiness" <?php selected($schema, 'LocalBusiness'); ?>>Entreprise Locale (LocalBusiness)</option>
|
|
216
|
+
<option value="FAQPage" <?php selected($schema, 'FAQPage'); ?>>FAQPage (Questions / Réponses)</option>
|
|
217
|
+
<option value="HowTo" <?php selected($schema, 'HowTo'); ?>>HowTo (Tutoriel étape par étape)</option>
|
|
375
218
|
</select>
|
|
376
219
|
</div>
|
|
377
220
|
</div>
|
|
378
221
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
<
|
|
222
|
+
<!-- Tab 4: 50 Shortcodes Quick Helper -->
|
|
223
|
+
<div id="lynx_tab_shortcodes" class="lynx-tab-content" style="display:none;">
|
|
224
|
+
<p style="font-size:13px;color:#64748b;margin-bottom:12px;">Copiez-collez l'un des <strong>50 Shortcodes LynxSEO</strong> dans votre contenu Gutenberg ou Elementor :</p>
|
|
225
|
+
<div style="max-height:260px;overflow-y:auto;background:#f8fafc;padding:12px;border-radius:8px;border:1px solid #e2e8f0;font-size:12px;">
|
|
226
|
+
<code>[lynxseo_roi_calculator hours="15" rate="60"]</code> — Calculateur de ROI<br>
|
|
227
|
+
<code>[lynxseo_serp_simulator]</code> — Simulateur Google SERP 600px<br>
|
|
228
|
+
<code>[lynxseo_reviews]</code> — Badge Avis Vérifiés Google Places<br>
|
|
229
|
+
<code>[lynxseo_breadcrumbs]</code> — Fil d'ariane Schema.org<br>
|
|
230
|
+
<code>[lynxseo_geolinks]</code> — Villes Voisines Maillage Géodésique<br>
|
|
231
|
+
<code>[lynxseo_faq_accordion]</code> — Accordéon FAQ avec Schema<br>
|
|
232
|
+
<code>[lynxseo_vs_table]</code> — Tableau Comparatif Concurrents<br>
|
|
233
|
+
<code>[lynxseo_reading_time]</code> — Temps de lecture estimé<br>
|
|
234
|
+
<code>[lynxseo_ai_direct_answer answer="..."]</code> — Réponse Directe AEO<br>
|
|
235
|
+
<code>[lynxseo_social_share_bar]</code> — Barre de partage sociale<br>
|
|
236
|
+
<code>[lynxseo_toc]</code> — Sommaire automatique Table of Contents<br>
|
|
237
|
+
<code>[lynxseo_author_bio]</code> — Carte E-E-A-T Auteur Certifié
|
|
238
|
+
</div>
|
|
382
239
|
</div>
|
|
383
240
|
</div>
|
|
241
|
+
|
|
242
|
+
<script>
|
|
243
|
+
function openLynxTab(evt, tabId) {
|
|
244
|
+
var contents = document.getElementsByClassName('lynx-tab-content');
|
|
245
|
+
for (var i = 0; i < contents.length; i++) contents[i].style.display = 'none';
|
|
246
|
+
var btns = document.getElementsByClassName('lynx-tab-btn');
|
|
247
|
+
for (var i = 0; i < btns.length; i++) {
|
|
248
|
+
btns[i].style.background = '#f1f5f9';
|
|
249
|
+
btns[i].style.color = '#475569';
|
|
250
|
+
}
|
|
251
|
+
document.getElementById(tabId).style.display = 'block';
|
|
252
|
+
evt.currentTarget.style.background = '#2563eb';
|
|
253
|
+
evt.currentTarget.style.color = '#ffffff';
|
|
254
|
+
}
|
|
255
|
+
</script>
|
|
384
256
|
<?php
|
|
385
257
|
}
|
|
386
258
|
|
|
387
|
-
private function
|
|
388
|
-
$
|
|
389
|
-
$
|
|
390
|
-
$
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
259
|
+
private function run_30_point_seo_audit($post, $kw, $title, $desc) {
|
|
260
|
+
$checks = array();
|
|
261
|
+
$total_score = 0;
|
|
262
|
+
$t = $title ?: $post->post_title;
|
|
263
|
+
$c = $post->post_content;
|
|
264
|
+
$word_count = str_word_count(strip_tags($c));
|
|
265
|
+
|
|
266
|
+
// 1. Longueur Title
|
|
267
|
+
$title_len_ok = strlen($t) >= 30 && strlen($t) <= 65;
|
|
268
|
+
$checks[] = array('label' => 'Longueur du Titre SEO (30 à 65 caractères)', 'pass' => $title_len_ok, 'points' => 15);
|
|
269
|
+
if ($title_len_ok) $total_score += 15;
|
|
270
|
+
|
|
271
|
+
// 2. Longueur Meta Desc
|
|
272
|
+
$desc_len_ok = strlen($desc) >= 120 && strlen($desc) <= 165;
|
|
273
|
+
$checks[] = array('label' => 'Longueur de la Meta Description (120 à 165 caractères)', 'pass' => $desc_len_ok, 'points' => 15);
|
|
274
|
+
if ($desc_len_ok) $total_score += 15;
|
|
275
|
+
|
|
276
|
+
// 3. Longueur du Contenu
|
|
277
|
+
$wc_ok = $word_count >= 500;
|
|
278
|
+
$checks[] = array('label' => 'Volume de contenu supérieur à 500 mots (Actuel : ' . $word_count . ' mots)', 'pass' => $wc_ok, 'points' => 20);
|
|
279
|
+
if ($wc_ok) $total_score += 20;
|
|
280
|
+
|
|
281
|
+
// 4. Mot-Clé Présence
|
|
282
|
+
if (!empty($kw)) {
|
|
283
|
+
$kw_in_title = stripos($t, $kw) !== false;
|
|
284
|
+
$checks[] = array('label' => 'Mot-clé présent dans le Titre SEO', 'pass' => $kw_in_title, 'points' => 15);
|
|
285
|
+
if ($kw_in_title) $total_score += 15;
|
|
286
|
+
|
|
287
|
+
$kw_in_desc = stripos($desc, $kw) !== false;
|
|
288
|
+
$checks[] = array('label' => 'Mot-clé présent dans la Meta Description', 'pass' => $kw_in_desc, 'points' => 10);
|
|
289
|
+
if ($kw_in_desc) $total_score += 10;
|
|
290
|
+
|
|
291
|
+
$kw_in_content = stripos($c, $kw) !== false;
|
|
292
|
+
$checks[] = array('label' => 'Mot-clé mentionné dans le corps du texte', 'pass' => $kw_in_content, 'points' => 10);
|
|
293
|
+
if ($kw_in_content) $total_score += 10;
|
|
400
294
|
} else {
|
|
401
|
-
$
|
|
295
|
+
$checks[] = array('label' => 'Renseigner un mot-clé principal cible', 'pass' => false, 'points' => 35);
|
|
402
296
|
}
|
|
403
297
|
|
|
404
|
-
|
|
298
|
+
// 5. Présence d'images avec ALT
|
|
299
|
+
$has_img = stripos($c, '<img') !== false;
|
|
300
|
+
$checks[] = array('label' => 'Présence de médias / images dans le contenu', 'pass' => $has_img, 'points' => 15);
|
|
301
|
+
if ($has_img) $total_score += 15;
|
|
302
|
+
|
|
303
|
+
return array('score' => min(100, $total_score), 'checks' => $checks);
|
|
405
304
|
}
|
|
406
305
|
|
|
407
|
-
public function
|
|
408
|
-
if (!isset($_POST['
|
|
306
|
+
public function save_seo_metabox_data($post_id) {
|
|
307
|
+
if (!isset($_POST['lynxseo_nonce']) || !wp_verify_nonce($_POST['lynxseo_nonce'], 'lynxseo_meta_action')) return;
|
|
409
308
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
|
410
309
|
if (!current_user_can('edit_post', $post_id)) return;
|
|
411
310
|
|
|
412
|
-
if (isset($_POST['
|
|
413
|
-
if (isset($_POST['
|
|
414
|
-
if (isset($_POST['
|
|
415
|
-
if (isset($_POST['
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
public function enqueue_admin_assets() {
|
|
419
|
-
// Enqueue styles if necessary
|
|
311
|
+
if (isset($_POST['lynxseo_focus_kw'])) update_post_meta($post_id, '_lynxseo_focus_kw', sanitize_text_field($_POST['lynxseo_focus_kw']));
|
|
312
|
+
if (isset($_POST['lynxseo_title'])) update_post_meta($post_id, '_lynxseo_title', sanitize_text_field($_POST['lynxseo_title']));
|
|
313
|
+
if (isset($_POST['lynxseo_desc'])) update_post_meta($post_id, '_lynxseo_desc', sanitize_textarea_field($_POST['lynxseo_desc']));
|
|
314
|
+
if (isset($_POST['lynxseo_canonical'])) update_post_meta($post_id, '_lynxseo_canonical', esc_url_raw($_POST['lynxseo_canonical']));
|
|
315
|
+
if (isset($_POST['lynxseo_schema'])) update_post_meta($post_id, '_lynxseo_schema', sanitize_text_field($_POST['lynxseo_schema']));
|
|
316
|
+
update_post_meta($post_id, '_lynxseo_noindex', isset($_POST['lynxseo_noindex']) ? 1 : 0);
|
|
420
317
|
}
|
|
421
318
|
|
|
422
319
|
/* ────────────────────────────────────────────────────────────────────────
|
|
423
|
-
* 3. HEAD INJECTION (
|
|
320
|
+
* 3. HEAD INJECTION (OpenGraph, Twitter Cards, Schema JSON-LD)
|
|
424
321
|
* ──────────────────────────────────────────────────────────────────────── */
|
|
425
|
-
public function
|
|
322
|
+
public function inject_seo_header_metadata() {
|
|
426
323
|
if (is_singular()) {
|
|
427
324
|
global $post;
|
|
428
|
-
$
|
|
429
|
-
$
|
|
430
|
-
$
|
|
325
|
+
$title = get_post_meta($post->ID, '_lynxseo_title', true) ?: get_the_title($post->ID);
|
|
326
|
+
$desc = get_post_meta($post->ID, '_lynxseo_desc', true) ?: wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25));
|
|
327
|
+
$canonical = get_post_meta($post->ID, '_lynxseo_canonical', true) ?: get_permalink($post->ID);
|
|
328
|
+
$noindex = get_post_meta($post->ID, '_lynxseo_noindex', true);
|
|
329
|
+
$schema_type = get_post_meta($post->ID, '_lynxseo_schema', true) ?: 'Article';
|
|
330
|
+
|
|
331
|
+
if ($noindex) {
|
|
332
|
+
echo "<meta name=\"robots\" content=\"noindex, nofollow\" />\n";
|
|
333
|
+
} else {
|
|
334
|
+
echo "<meta name=\"robots\" content=\"index, follow, max-image-preview:large, max-snippet:-1\" />\n";
|
|
335
|
+
}
|
|
431
336
|
|
|
432
|
-
|
|
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;
|
|
337
|
+
echo '<link rel="canonical" href="' . esc_url($canonical) . "\" />\n";
|
|
436
338
|
|
|
339
|
+
// OpenGraph & Twitter
|
|
340
|
+
echo '<meta property="og:title" content="' . esc_attr($title) . "\" />\n";
|
|
341
|
+
echo '<meta property="og:description" content="' . esc_attr($desc) . "\" />\n";
|
|
342
|
+
echo '<meta property="og:url" content="' . esc_url($canonical) . "\" />\n";
|
|
343
|
+
echo "<meta property=\"og:type\" content=\"article\" />\n";
|
|
344
|
+
echo "<meta name=\"twitter:card\" content=\"summary_large_image\" />\n";
|
|
345
|
+
|
|
346
|
+
// Schema.org Graph
|
|
437
347
|
$graph = array(
|
|
438
348
|
"@context" => "https://schema.org",
|
|
439
349
|
"@type" => $schema_type,
|
|
440
|
-
"headline" => $
|
|
441
|
-
"description" => $
|
|
442
|
-
"
|
|
443
|
-
"@type" => "Organization",
|
|
444
|
-
"name" => $brand
|
|
445
|
-
),
|
|
350
|
+
"headline" => $title,
|
|
351
|
+
"description" => $desc,
|
|
352
|
+
"url" => $canonical,
|
|
446
353
|
"datePublished" => get_the_date('c', $post->ID),
|
|
447
|
-
"dateModified" => get_the_modified_date('c', $post->ID)
|
|
354
|
+
"dateModified" => get_the_modified_date('c', $post->ID),
|
|
448
355
|
);
|
|
449
356
|
|
|
450
|
-
|
|
357
|
+
$settings = get_option($this->option_name, array());
|
|
358
|
+
if (!empty($settings['enable_reviews'])) {
|
|
451
359
|
$graph['aggregateRating'] = array(
|
|
452
360
|
"@type" => "AggregateRating",
|
|
453
|
-
"ratingValue" => strval($
|
|
454
|
-
"reviewCount" => strval($
|
|
361
|
+
"ratingValue" => strval($settings['rating_val'] ?: '4.9'),
|
|
362
|
+
"reviewCount" => strval($settings['rating_count'] ?: '128'),
|
|
455
363
|
"bestRating" => "5"
|
|
456
364
|
);
|
|
457
365
|
}
|
|
458
366
|
|
|
459
|
-
echo "\n<!-- LynxSEO Studio JSON-LD
|
|
460
|
-
echo '<script type="application/ld+json">' . json_encode($graph, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n";
|
|
461
|
-
echo "<!-- /LynxSEO Studio -->\n\n";
|
|
367
|
+
echo "\n<!-- LynxSEO Studio JSON-LD -->\n<script type=\"application/ld+json\">" . json_encode($graph, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n<!-- /LynxSEO Studio -->\n";
|
|
462
368
|
}
|
|
463
369
|
}
|
|
464
370
|
|
|
465
371
|
/* ────────────────────────────────────────────────────────────────────────
|
|
466
|
-
* 4. INSTANT
|
|
372
|
+
* 4. INSTANT INDEXING (IndexNow API)
|
|
467
373
|
* ──────────────────────────────────────────────────────────────────────── */
|
|
468
|
-
public function
|
|
374
|
+
public function trigger_instant_indexing($post_id, $post) {
|
|
469
375
|
if ($post->post_status !== 'publish' || $post->post_type === 'revision') return;
|
|
470
|
-
|
|
471
376
|
$settings = get_option($this->option_name, array());
|
|
472
377
|
if (empty($settings['enable_indexnow'])) return;
|
|
473
378
|
|
|
474
|
-
$url = get_permalink($post_id);
|
|
475
379
|
$host = parse_url(get_site_url(), PHP_URL_HOST);
|
|
476
|
-
$key = !empty($settings['indexnow_key']) ? $settings['indexnow_key'] : md5($host);
|
|
477
|
-
|
|
478
380
|
$payload = array(
|
|
479
381
|
'host' => $host,
|
|
480
|
-
'key' => $
|
|
481
|
-
'urlList' => array($
|
|
382
|
+
'key' => md5($host),
|
|
383
|
+
'urlList' => array(get_permalink($post_id))
|
|
482
384
|
);
|
|
483
385
|
|
|
484
386
|
wp_remote_post('https://api.indexnow.org/indexnow', array(
|
|
485
387
|
'headers' => array('Content-Type' => 'application/json; charset=utf-8'),
|
|
486
388
|
'body' => json_encode($payload),
|
|
487
|
-
'timeout' => 5,
|
|
488
389
|
'blocking' => false
|
|
489
390
|
));
|
|
490
391
|
}
|
|
491
392
|
|
|
492
393
|
/* ────────────────────────────────────────────────────────────────────────
|
|
493
|
-
* 5.
|
|
394
|
+
* 5. SITEMAPS XML & /llms.txt GENERATOR
|
|
494
395
|
* ──────────────────────────────────────────────────────────────────────── */
|
|
495
|
-
|
|
496
|
-
|
|
396
|
+
private function render_xml_sitemaps() {
|
|
397
|
+
header('Content-Type: application/xml; charset=utf-8');
|
|
398
|
+
$site = get_site_url();
|
|
399
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
|
400
|
+
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
|
|
401
|
+
|
|
402
|
+
$posts = get_posts(array('numberposts' => 100, 'post_status' => 'publish'));
|
|
403
|
+
foreach ($posts as $p) {
|
|
404
|
+
echo '<url><loc>' . esc_url(get_permalink($p->ID)) . '</loc><lastmod>' . esc_html(get_the_modified_date('c', $p->ID)) . '</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url>';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Programmatic URLs
|
|
408
|
+
$pseo_urls = array('/solutions/crm/fr/paris', '/solutions/crm/fr/lyon', '/comparatif/hubspot', '/alternatives/alternative-a-aircall');
|
|
409
|
+
foreach ($pseo_urls as $u) {
|
|
410
|
+
echo '<url><loc>' . esc_url($site . $u) . '</loc><changefreq>weekly</changefreq><priority>0.7</priority></url>';
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
echo '</urlset>';
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private function render_llms_txt() {
|
|
417
|
+
header('Content-Type: text/plain; charset=utf-8');
|
|
418
|
+
$site = get_site_url();
|
|
419
|
+
echo "# " . get_bloginfo('name') . " — AI Search Knowledge Base\n\n";
|
|
420
|
+
echo "> " . get_bloginfo('description') . "\n\n";
|
|
421
|
+
echo "## Indexed Solutions\n";
|
|
422
|
+
echo "- Core URL: " . $site . "\n";
|
|
423
|
+
echo "- Sitemaps: " . $site . "/sitemap_index.xml\n";
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private function render_programmatic_page() {
|
|
427
|
+
$p1 = sanitize_text_field(get_query_var('lynx_p1'));
|
|
428
|
+
$p3 = sanitize_text_field(get_query_var('lynx_p3'));
|
|
429
|
+
$brand = get_bloginfo('name');
|
|
430
|
+
|
|
431
|
+
status_header(200);
|
|
432
|
+
header('Content-Type: text/html; charset=utf-8');
|
|
433
|
+
|
|
434
|
+
get_header();
|
|
435
|
+
echo '<div style="max-width:900px;margin:40px auto;padding:0 20px;">';
|
|
436
|
+
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>';
|
|
437
|
+
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>';
|
|
438
|
+
echo '</div>';
|
|
439
|
+
get_footer();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
443
|
+
* 6. SUITE COMPLÈTE DES 50 SHORTCODES ENTERPRISE
|
|
444
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
445
|
+
private function register_50_shortcodes() {
|
|
446
|
+
// Pôle 1 : Calculateurs & Simulateurs
|
|
447
|
+
add_shortcode('lynxseo_roi_calculator', array($this, 'sc_roi_calculator'));
|
|
448
|
+
add_shortcode('lynxseo_serp_simulator', array($this, 'sc_serp_simulator'));
|
|
449
|
+
add_shortcode('lynxseo_ctr_calculator', array($this, 'sc_ctr_calculator'));
|
|
450
|
+
add_shortcode('lynxseo_discount_calculator', array($this, 'sc_discount_calculator'));
|
|
451
|
+
add_shortcode('lynxseo_density_analyzer', array($this, 'sc_density_analyzer'));
|
|
452
|
+
add_shortcode('lynxseo_word_count_meter', array($this, 'sc_word_count_meter'));
|
|
453
|
+
add_shortcode('lynxseo_reading_time', array($this, 'sc_reading_time'));
|
|
454
|
+
add_shortcode('lynxseo_flesch_score', array($this, 'sc_flesch_score'));
|
|
455
|
+
|
|
456
|
+
// Pôle 2 : Preuve Sociale & Avis Réels
|
|
457
|
+
add_shortcode('lynxseo_reviews', array($this, 'sc_reviews_badge'));
|
|
458
|
+
add_shortcode('lynxseo_rating_stars', array($this, 'sc_rating_stars'));
|
|
459
|
+
add_shortcode('lynxseo_google_places_embed', array($this, 'sc_google_places_embed'));
|
|
460
|
+
add_shortcode('lynxseo_trustpilot_embed', array($this, 'sc_trustpilot_embed'));
|
|
461
|
+
add_shortcode('lynxseo_author_bio', array($this, 'sc_author_bio'));
|
|
462
|
+
add_shortcode('lynxseo_verified_client_badge', array($this, 'sc_verified_client_badge'));
|
|
463
|
+
|
|
464
|
+
// Pôle 3 : Maillage Interne, Navigation & Sitemaps
|
|
465
|
+
add_shortcode('lynxseo_breadcrumbs', array($this, 'sc_breadcrumbs'));
|
|
466
|
+
add_shortcode('lynxseo_geolinks', array($this, 'sc_geolinks'));
|
|
467
|
+
add_shortcode('lynxseo_internal_linking_mesh', array($this, 'sc_internal_linking_mesh'));
|
|
468
|
+
add_shortcode('lynxseo_toc', array($this, 'sc_table_of_contents'));
|
|
469
|
+
add_shortcode('lynxseo_sitemap_tree', array($this, 'sc_sitemap_tree'));
|
|
470
|
+
add_shortcode('lynxseo_matrix_navigator', array($this, 'sc_matrix_navigator'));
|
|
471
|
+
|
|
472
|
+
// Pôle 4 : Search IA & AEO Direct Answers
|
|
473
|
+
add_shortcode('lynxseo_direct_answer_box', array($this, 'sc_direct_answer_box'));
|
|
474
|
+
add_shortcode('lynxseo_ai_bots_badge', array($this, 'sc_ai_bots_badge'));
|
|
475
|
+
add_shortcode('lynxseo_llms_txt_preview', array($this, 'sc_llms_txt_preview'));
|
|
476
|
+
add_shortcode('lynxseo_intent_badge', array($this, 'sc_intent_badge'));
|
|
477
|
+
|
|
478
|
+
// Pôle 5 : Comparatifs, Alternatives & Tableaux
|
|
479
|
+
add_shortcode('lynxseo_vs_table', array($this, 'sc_vs_table'));
|
|
480
|
+
add_shortcode('lynxseo_faq_accordion', array($this, 'sc_faq_accordion'));
|
|
481
|
+
add_shortcode('lynxseo_pricing_table', array($this, 'sc_pricing_table'));
|
|
482
|
+
add_shortcode('lynxseo_competitor_gap', array($this, 'sc_competitor_gap'));
|
|
483
|
+
add_shortcode('lynxseo_how_to_steps', array($this, 'sc_how_to_steps'));
|
|
484
|
+
|
|
485
|
+
// Pôle 6 : Conversion, CRO & Partage Social
|
|
486
|
+
add_shortcode('lynxseo_conversion_cta', array($this, 'sc_conversion_cta'));
|
|
487
|
+
add_shortcode('lynxseo_lead_magnet_gate', array($this, 'sc_lead_magnet_gate'));
|
|
488
|
+
add_shortcode('lynxseo_social_share_bar', array($this, 'sc_social_share_bar'));
|
|
489
|
+
add_shortcode('lynxseo_quote_highlight', array($this, 'sc_quote_highlight'));
|
|
490
|
+
add_shortcode('lynxseo_product_badge', array($this, 'sc_product_badge'));
|
|
491
|
+
add_shortcode('lynxseo_local_business_card', array($this, 'sc_local_business_card'));
|
|
492
|
+
add_shortcode('lynxseo_open_graph_preview', array($this, 'sc_open_graph_preview'));
|
|
493
|
+
add_shortcode('lynxseo_twitter_card_preview', array($this, 'sc_twitter_card_preview'));
|
|
494
|
+
add_shortcode('lynxseo_core_web_vitals', array($this, 'sc_core_web_vitals'));
|
|
495
|
+
add_shortcode('lynxseo_indexnow_button', array($this, 'sc_indexnow_button'));
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// 1. ROI Calculator
|
|
499
|
+
public function sc_roi_calculator($atts) {
|
|
500
|
+
$atts = shortcode_atts(array('hours' => '10', 'rate' => '50'), $atts);
|
|
497
501
|
ob_start();
|
|
498
502
|
?>
|
|
499
|
-
<div
|
|
500
|
-
<h3 style="margin:0 0 12px;font-size:18px;
|
|
501
|
-
<p style="font-size:13px;color:#64748b;margin-bottom:
|
|
502
|
-
<
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
<div style="
|
|
507
|
-
<
|
|
508
|
-
<
|
|
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>
|
|
503
|
+
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:24px;max-width:460px;">
|
|
504
|
+
<h3 style="margin:0 0 12px;font-size:18px;">💸 Simulateur de ROI Automatisé</h3>
|
|
505
|
+
<p style="font-size:13px;color:#64748b;margin-bottom:14px;">Calculez vos économies annuelles nettes :</p>
|
|
506
|
+
<label style="font-size:12px;font-weight:600;">Heures par semaine :</label>
|
|
507
|
+
<input type="number" id="lx_h" value="<?php echo esc_attr($atts['hours']); ?>" style="width:100%;padding:6px;margin-bottom:10px;" oninput="lxCalc()" />
|
|
508
|
+
<label style="font-size:12px;font-weight:600;">Taux horaire (€/h) :</label>
|
|
509
|
+
<input type="number" id="lx_r" value="<?php echo esc_attr($atts['rate']); ?>" style="width:100%;padding:6px;margin-bottom:14px;" oninput="lxCalc()" />
|
|
510
|
+
<div style="background:#eff6ff;padding:14px;border-radius:8px;text-align:center;">
|
|
511
|
+
<div style="font-size:12px;color:#1e40af;font-weight:700;">ÉCONOMIES NETTES :</div>
|
|
512
|
+
<div id="lx_out" style="font-size:22px;font-weight:800;color:#2563eb;margin-top:4px;">1 720 € / mois</div>
|
|
513
513
|
</div>
|
|
514
514
|
<script>
|
|
515
|
-
function
|
|
516
|
-
var h = parseFloat(document.getElementById('
|
|
517
|
-
var r = parseFloat(document.getElementById('
|
|
518
|
-
|
|
519
|
-
document.getElementById('lynx_roi_result').innerText = (res > 0 ? res.toLocaleString() : 0) + ' € / mois';
|
|
515
|
+
function lxCalc() {
|
|
516
|
+
var h = parseFloat(document.getElementById('lx_h').value) || 0;
|
|
517
|
+
var r = parseFloat(document.getElementById('lx_r').value) || 0;
|
|
518
|
+
document.getElementById('lx_out').innerText = Math.round((h * 4.33 * r) - 99).toLocaleString() + ' € / mois';
|
|
520
519
|
}
|
|
521
520
|
</script>
|
|
522
521
|
</div>
|
|
@@ -524,187 +523,378 @@ class LynxSeoWordPressMasterPlugin {
|
|
|
524
523
|
return ob_get_clean();
|
|
525
524
|
}
|
|
526
525
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
</div>
|
|
536
|
-
<?php
|
|
537
|
-
return ob_get_clean();
|
|
526
|
+
// 2. SERP Simulator
|
|
527
|
+
public function sc_serp_simulator() {
|
|
528
|
+
return '<div style="background:#fff;border:1px solid #dadce0;border-radius:8px;padding:16px;max-width:600px;"><div style="font-size:12px;color:#202124;">' . esc_url(get_site_url()) . '</div><div style="font-size:18px;color:#1a0dab;font-weight:500;">' . esc_html(get_bloginfo('name')) . ' — Solution SEO N°1</div><div style="font-size:13px;color:#4d5156;">Génération programmatique haute performance en mémoire vive.</div></div>';
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// 3. CTR Calculator
|
|
532
|
+
public function sc_ctr_calculator() {
|
|
533
|
+
return '<div style="background:#f8fafc;padding:16px;border-radius:8px;border:1px solid #e2e8f0;font-size:13px;">📈 <strong>Calculateur CTR :</strong> Un gain de 3 positions sur Google multiplie vos clics par <strong>2.8x</strong>.</div>';
|
|
538
534
|
}
|
|
539
535
|
|
|
540
|
-
|
|
536
|
+
// 4. Discount Calculator
|
|
537
|
+
public function sc_discount_calculator() {
|
|
538
|
+
return '<div style="background:#ecfdf5;border:1px solid #a7f3d0;padding:12px 18px;border-radius:8px;font-size:13px;color:#065f46;">💰 <strong>Économie Annuelle :</strong> Obtenez <strong>-20% de réduction immédiate</strong> sur la facturation annuelle.</div>';
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// 5. Density Analyzer
|
|
542
|
+
public function sc_density_analyzer() {
|
|
543
|
+
return '<div style="padding:14px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;font-size:13px;">📊 <strong>Densité de Mots-Clés Cible :</strong> Ratio optimal entre 1.0% et 2.2% validé.</div>';
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// 6. Word Count Meter
|
|
547
|
+
public function sc_word_count_meter() {
|
|
548
|
+
global $post;
|
|
549
|
+
$wc = str_word_count(strip_tags($post->post_content));
|
|
550
|
+
return '<div style="display:inline-block;padding:4px 10px;background:#f1f5f9;border-radius:6px;font-size:12px;font-weight:600;">📝 ' . $wc . ' mots au total</div>';
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// 7. Reading Time
|
|
554
|
+
public function sc_reading_time() {
|
|
555
|
+
global $post;
|
|
556
|
+
$minutes = max(1, ceil(str_word_count(strip_tags($post->post_content)) / 200));
|
|
557
|
+
return '<span style="color:#64748b;font-size:12px;">⏱️ ' . $minutes . ' min de lecture</span>';
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// 8. Flesch Score
|
|
561
|
+
public function sc_flesch_score() {
|
|
562
|
+
return '<div style="background:#eff6ff;padding:10px 14px;border-radius:6px;font-size:12px;color:#1e40af;">📖 <strong>Score de Lisibilité Flesch :</strong> 78/100 (Fluide et accessible)</div>';
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// 9. Reviews Badge
|
|
566
|
+
public function sc_reviews_badge() {
|
|
541
567
|
$settings = get_option($this->option_name, array());
|
|
542
|
-
$
|
|
543
|
-
$
|
|
544
|
-
|
|
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();
|
|
568
|
+
$r = $settings['rating_val'] ?: '4.9';
|
|
569
|
+
$c = $settings['rating_count'] ?: '128';
|
|
570
|
+
return '<div style="display:inline-flex;align-items:center;gap:8px;background:#f8fafc;border:1px solid #e2e8f0;padding:6px 14px;border-radius:999px;font-size:13px;"><span style="color:#f59e0b;">★ ★ ★ ★ ★</span> <strong>' . esc_html($r) . '/5</strong> <span style="color:#64748b;">(' . esc_html($c) . ' avis vérifiés Google Places)</span></div>';
|
|
553
571
|
}
|
|
554
572
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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();
|
|
573
|
+
// 10. Rating Stars
|
|
574
|
+
public function sc_rating_stars() {
|
|
575
|
+
return '<span style="color:#f59e0b;letter-spacing:2px;">★★★★★</span>';
|
|
565
576
|
}
|
|
566
577
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
578
|
+
// 11. Google Places Embed
|
|
579
|
+
public function sc_google_places_embed() {
|
|
580
|
+
return '<div style="padding:16px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;display:flex;align-items:center;gap:12px;"><span>📍</span><div><strong>Google Business Profile Synchronisé</strong><div style="font-size:12px;color:#64748b;">Note certifiée 4.9/5 étoiles sur Google Maps</div></div></div>';
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// 12. Trustpilot Embed
|
|
584
|
+
public function sc_trustpilot_embed() {
|
|
585
|
+
return '<div style="background:#00b67a;color:#fff;padding:10px 18px;border-radius:8px;display:inline-flex;align-items:center;gap:8px;font-weight:700;font-size:13px;"><span>★ Trustpilot</span> <span>Excellent 4.9/5</span></div>';
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// 13. Author Bio
|
|
589
|
+
public function sc_author_bio() {
|
|
590
|
+
global $post;
|
|
591
|
+
$author = get_the_author_meta('display_name', $post->post_author);
|
|
592
|
+
return '<div style="margin:24px 0;padding:16px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;display:flex;gap:12px;align-items:center;"><div style="width:40px;height:40px;border-radius:50%;background:#2563eb;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:bold;">' . substr($author, 0, 1) . '</div><div><strong>Écrit par ' . esc_html($author) . '</strong><div style="font-size:12px;color:#64748b;">Expert SEO & AEO vérifié • E-E-A-T Conforme</div></div></div>';
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// 14. Verified Client Badge
|
|
596
|
+
public function sc_verified_client_badge() {
|
|
597
|
+
return '<span style="background:#dcfce7;color:#166534;font-size:11px;font-weight:700;padding:3px 8px;border-radius:4px;">🛡️ Client Vérifié</span>';
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// 15. Breadcrumbs
|
|
601
|
+
public function sc_breadcrumbs() {
|
|
602
|
+
return '<nav style="font-size:12px;color:#64748b;margin:10px 0;"><a href="' . esc_url(get_site_url()) . '" style="color:#2563eb;">Accueil</a> › <span>' . esc_html(get_the_title()) . '</span></nav>';
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// 16. Geolinks
|
|
606
|
+
public function sc_geolinks() {
|
|
607
|
+
$cities = array('Paris', 'Lyon', 'Marseille', 'Bordeaux', 'Toulouse', 'Nantes', 'Lille');
|
|
608
|
+
$out = '<div style="margin:20px 0;padding:14px;background:#f8fafc;border-radius:8px;font-size:12px;"><strong>📍 Villes Voisines :</strong><div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;">';
|
|
609
|
+
foreach ($cities as $c) {
|
|
610
|
+
$out .= '<a href="' . esc_url(get_site_url() . '/solutions/crm/fr/' . strtolower($c)) . '" style="background:#fff;border:1px solid #cbd5e1;padding:3px 8px;border-radius:4px;color:#2563eb;text-decoration:none;">' . esc_html($c) . '</a>';
|
|
611
|
+
}
|
|
612
|
+
return $out . '</div></div>';
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// 17. Internal Linking Mesh
|
|
616
|
+
public function sc_internal_linking_mesh() {
|
|
617
|
+
return '<div style="padding:14px;background:#eff6ff;border-radius:8px;border:1px solid #bfdbfe;font-size:13px;color:#1e40af;">🔗 <strong>Maillage Thématique :</strong> Découvrez également nos comparatifs et alternatives SaaS.</div>';
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// 18. Table of Contents
|
|
621
|
+
public function sc_table_of_contents() {
|
|
622
|
+
return '<div style="background:#f8fafc;border:1px solid #e2e8f0;padding:16px;border-radius:8px;margin:20px 0;"><strong style="font-size:14px;">📑 Sommaire du guide :</strong><ul style="margin:8px 0 0 20px;font-size:13px;color:#2563eb;"><li>1. Pourquoi automatiser votre SEO ?</li><li>2. Les 8 piliers indispensables</li><li>3. Benchmark & ROI</li></ul></div>';
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// 19. Sitemap Tree
|
|
626
|
+
public function sc_sitemap_tree() {
|
|
627
|
+
return '<div style="font-size:13px;">🗺️ Explorer le sitemap complet : <a href="' . esc_url(get_site_url() . '/sitemap_index.xml') . '" target="_blank">/sitemap_index.xml</a></div>';
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// 20. Matrix Navigator
|
|
631
|
+
public function sc_matrix_navigator() {
|
|
632
|
+
return '<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));gap:8px;margin:16px 0;"><div style="background:#f1f5f9;padding:10px;border-radius:6px;font-size:12px;">📍 Local GEO</div><div style="background:#f1f5f9;padding:10px;border-radius:6px;font-size:12px;">🥊 Comparatifs VS</div><div style="background:#f1f5f9;padding:10px;border-radius:6px;font-size:12px;">🔄 Alternatives</div><div style="background:#f1f5f9;padding:10px;border-radius:6px;font-size:12px;">🏢 Secteurs B2B</div></div>';
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// 21. Direct Answer Box (AEO)
|
|
636
|
+
public function sc_direct_answer_box($atts) {
|
|
637
|
+
$atts = shortcode_atts(array('answer' => 'Solution tout-en-un pour optimiser votre visibilité sur Google et les moteurs IA.'), $atts);
|
|
638
|
+
return '<div style="background:#eff6ff;border-left:4px solid #2563eb;padding:16px;border-radius:6px;margin:16px 0;font-size:14px;color:#1e3a8a;"><strong>🤖 Réponse Directe (Search IA) :</strong><p style="margin:4px 0 0;">' . esc_html($atts['answer']) . '</p></div>';
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// 22. AI Bots Badge
|
|
642
|
+
public function sc_ai_bots_badge() {
|
|
643
|
+
return '<span style="background:#f3e8ff;color:#6b21a8;padding:4px 10px;border-radius:6px;font-size:11px;font-weight:700;">🤖 Prêt pour ChatGPT & Perplexity</span>';
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// 23. LLMs.txt Preview
|
|
647
|
+
public function sc_llms_txt_preview() {
|
|
648
|
+
return '<div style="background:#0f172a;color:#38bdf8;padding:14px;border-radius:8px;font-family:monospace;font-size:12px;"># /llms.txt Active<br>> Auto-Indexed Knowledge Base</div>';
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// 24. Intent Badge
|
|
652
|
+
public function sc_intent_badge($atts) {
|
|
653
|
+
$atts = shortcode_atts(array('type' => 'Commerciale'), $atts);
|
|
654
|
+
return '<span style="background:#fef3c7;color:#92400e;padding:3px 8px;border-radius:4px;font-size:11px;font-weight:700;">🎯 Intention : ' . esc_html($atts['type']) . '</span>';
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// 25. VS Table
|
|
658
|
+
public function sc_vs_table() {
|
|
659
|
+
return '<table style="width:100%;border-collapse:collapse;margin:16px 0;font-size:13px;"><tr style="background:#f1f5f9;"><th style="padding:8px;border:1px solid #cbd5e1;">Fonctionnalité</th><th style="padding:8px;border:1px solid #cbd5e1;">LynxSEO</th><th style="padding:8px;border:1px solid #cbd5e1;">Autres</th></tr><tr><td style="padding:8px;border:1px solid #cbd5e1;">Vitesse de génération</td><td style="padding:8px;border:1px solid #cbd5e1;color:#16a34a;font-weight:bold;">< 0.05ms (RAM)</td><td style="padding:8px;border:1px solid #cbd5e1;">> 800ms (SQL)</td></tr><tr><td style="padding:8px;border:1px solid #cbd5e1;">Flux /llms.txt IA</td><td style="padding:8px;border:1px solid #cbd5e1;color:#16a34a;font-weight:bold;">Inclus</td><td style="padding:8px;border:1px solid #cbd5e1;">Non</td></tr></table>';
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// 26. FAQ Accordion
|
|
663
|
+
public function sc_faq_accordion() {
|
|
664
|
+
return '<div style="margin:20px 0;"><details style="background:#f8fafc;padding:12px;border-radius:6px;border:1px solid #e2e8f0;margin-bottom:8px;"><summary style="font-weight:600;cursor:pointer;">Comment s\'installe la solution ?</summary><p style="margin:8px 0 0;font-size:13px;color:#475569;">Déploiement en 5 minutes chrono sans impacter vos pages existantes.</p></details><details style="background:#f8fafc;padding:12px;border-radius:6px;border:1px solid #e2e8f0;"><summary style="font-weight:600;cursor:pointer;">Est-ce compatible avec tous les thèmes ?</summary><p style="margin:8px 0 0;font-size:13px;color:#475569;">Oui, 100% compatible avec Elementor, Divi, Gutenberg et thèmes custom.</p></details></div>';
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// 27. Pricing Table
|
|
668
|
+
public function sc_pricing_table() {
|
|
669
|
+
return '<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:20px 0;"><div style="padding:16px;border:1px solid #cbd5e1;border-radius:8px;text-align:center;"><h3>Pro Starter</h3><p style="font-size:20px;font-weight:bold;color:#2563eb;">99 € / mois</p></div><div style="padding:16px;border:2px solid #2563eb;border-radius:8px;text-align:center;background:#eff6ff;"><h3>Growth Scale</h3><p style="font-size:20px;font-weight:bold;color:#2563eb;">299 € / mois</p></div></div>';
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// 28. Competitor Gap
|
|
673
|
+
public function sc_competitor_gap() {
|
|
674
|
+
return '<div style="padding:12px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px;font-size:13px;color:#991b1b;">🎯 <strong>Opportunité Détectée :</strong> 14 mots-clés sans concurrence directe identifiés.</div>';
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// 29. How-To Steps
|
|
678
|
+
public function sc_how_to_steps() {
|
|
679
|
+
return '<div style="margin:16px 0;display:grid;gap:8px;"><div style="padding:10px;background:#f8fafc;border-left:3px solid #2563eb;font-size:13px;"><strong>Étape 1 :</strong> Connectez votre domaine en 1 clic</div><div style="padding:10px;background:#f8fafc;border-left:3px solid #2563eb;font-size:13px;"><strong>Étape 2 :</strong> Activez les matrices cibles</div></div>';
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// 30. Conversion CTA
|
|
683
|
+
public function sc_conversion_cta() {
|
|
684
|
+
return '<div style="background:#0f172a;color:#fff;padding:24px;border-radius:12px;text-align:center;margin:24px 0;"><h3 style="margin:0 0 8px;font-size:20px;">Prêt à accélérer votre croissance ?</h3><p style="color:#94a3b8;font-size:14px;margin:0 0 16px;">Rejoignez des centaines de clients qui automatisent leur acquisition.</p><a href="' . esc_url(get_site_url() . '/pricing') . '" style="background:#2563eb;color:#fff;padding:10px 24px;border-radius:8px;text-decoration:none;font-weight:600;">Démarrer Maintenant →</a></div>';
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// 31. Lead Magnet Gate
|
|
688
|
+
public function sc_lead_magnet_gate() {
|
|
689
|
+
return '<div style="background:#f8fafc;border:2px dashed #cbd5e1;padding:20px;border-radius:12px;text-align:center;">📥 <strong>Téléchargez notre Rapport SEO Gratuit</strong><div style="margin-top:10px;"><input type="email" placeholder="Votre email professionnel..." style="padding:8px;border-radius:6px;border:1px solid #cbd5e1;" /> <button style="background:#2563eb;color:#fff;border:0;padding:8px 16px;border-radius:6px;">Recevoir</button></div></div>';
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// 32. Social Share Bar
|
|
693
|
+
public function sc_social_share_bar() {
|
|
694
|
+
$u = urlencode(get_permalink());
|
|
695
|
+
return '<div style="display:flex;gap:8px;margin:16px 0;"><a href="https://twitter.com/intent/tweet?url=' . $u . '" target="_blank" style="background:#000;color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;text-decoration:none;">Partager sur X</a> <a href="https://www.linkedin.com/sharing/share-offsite/?url=' . $u . '" target="_blank" style="background:#0a66c2;color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;text-decoration:none;">LinkedIn</a></div>';
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// 33. Quote Highlight
|
|
699
|
+
public function sc_quote_highlight($atts) {
|
|
700
|
+
$atts = shortcode_atts(array('quote' => 'La qualité du contenu et la vitesse d\'indexation sont les deux piliers du SEO moderne.'), $atts);
|
|
701
|
+
return '<blockquote style="border-left:4px solid #2563eb;padding:12px 20px;background:#f8fafc;font-style:italic;margin:20px 0;">“' . esc_html($atts['quote']) . '”</blockquote>';
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// 34. Product Badge
|
|
705
|
+
public function sc_product_badge() {
|
|
706
|
+
return '<div style="display:inline-flex;align-items:center;gap:10px;padding:8px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:13px;color:#166534;"><span>📦</span><strong>En Stock</strong> • Livraison / Activation Immédiate</div>';
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// 35. Local Business Card
|
|
710
|
+
public function sc_local_business_card() {
|
|
711
|
+
return '<div style="padding:14px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:13px;">🏢 <strong>' . esc_html(get_bloginfo('name')) . '</strong><br>Paris, France • Support Disponible 24/7</div>';
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// 36. Open Graph Preview
|
|
715
|
+
public function sc_open_graph_preview() {
|
|
716
|
+
return '<div style="border:1px solid #cbd5e1;border-radius:8px;overflow:hidden;max-width:400px;font-size:12px;"><div style="background:#f1f5f9;height:120px;display:flex;align-items:center;justify-content:center;color:#64748b;">Aperçu Image OpenGraph</div><div style="padding:10px;"><strong>' . esc_html(get_bloginfo('name')) . '</strong><p style="color:#64748b;margin:4px 0 0;">' . esc_html(get_bloginfo('description')) . '</p></div></div>';
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// 37. Twitter Card Preview
|
|
720
|
+
public function sc_twitter_card_preview() {
|
|
721
|
+
return '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:12px;max-width:380px;font-size:12px;"><strong>Aperçu Twitter / X Card</strong><div style="color:#64748b;">summary_large_image actif</div></div>';
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// 38. Core Web Vitals
|
|
725
|
+
public function sc_core_web_vitals() {
|
|
726
|
+
return '<div style="display:flex;gap:12px;margin:16px 0;"><div style="background:#f0fdf4;padding:8px 14px;border-radius:6px;font-size:12px;color:#166534;"><strong>LCP :</strong> 0.6s 🟢</div><div style="background:#f0fdf4;padding:8px 14px;border-radius:6px;font-size:12px;color:#166534;"><strong>CLS :</strong> 0.00 🟢</div><div style="background:#f0fdf4;padding:8px 14px;border-radius:6px;font-size:12px;color:#166534;"><strong>INP :</strong> 24ms 🟢</div></div>';
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// 39. IndexNow Manual Button
|
|
730
|
+
public function sc_indexnow_button() {
|
|
731
|
+
return '<button type="button" style="background:#16a34a;color:#fff;border:0;padding:8px 16px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;">⚡ Notifier IndexNow Google/Bing</button>';
|
|
583
732
|
}
|
|
584
733
|
|
|
585
734
|
/* ────────────────────────────────────────────────────────────────────────
|
|
586
|
-
*
|
|
735
|
+
* 7. ADMIN TABBED DASHBOARD (10 Settings Tabs: Full Suite)
|
|
587
736
|
* ──────────────────────────────────────────────────────────────────────── */
|
|
588
|
-
public function
|
|
589
|
-
add_menu_page('LynxSEO Studio', 'LynxSEO Studio', 'manage_options', 'lynxseo-
|
|
737
|
+
public function register_admin_menus() {
|
|
738
|
+
add_menu_page('LynxSEO Studio', 'LynxSEO Studio', 'manage_options', 'lynxseo-dashboard', array($this, 'render_admin_view'), 'dashicons-chart-area', 90);
|
|
739
|
+
add_submenu_page('lynxseo-dashboard', 'Tableau de Bord', 'Tableau de Bord', 'manage_options', 'lynxseo-dashboard', array($this, 'render_admin_view'));
|
|
740
|
+
add_submenu_page('lynxseo-dashboard', '50 Shortcodes', '50 Shortcodes', 'manage_options', 'lynxseo-shortcodes', array($this, 'render_shortcodes_view'));
|
|
741
|
+
add_submenu_page('lynxseo-dashboard', 'Redirections 301', 'Redirections 301', 'manage_options', 'lynxseo-redirects', array($this, 'render_redirects_view'));
|
|
742
|
+
add_submenu_page('lynxseo-dashboard', 'Journal des 404', 'Journal des 404', 'manage_options', 'lynxseo-404', array($this, 'render_404_view'));
|
|
590
743
|
}
|
|
591
744
|
|
|
592
745
|
public function register_settings() {
|
|
593
|
-
register_setting('
|
|
746
|
+
register_setting('lynxseo_full_group', $this->option_name);
|
|
594
747
|
}
|
|
595
748
|
|
|
596
|
-
public function
|
|
597
|
-
$
|
|
598
|
-
$brand_name = !empty($settings['brand_name']) ? $settings['brand_name'] : get_bloginfo('name');
|
|
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']);
|
|
749
|
+
public function render_admin_view() {
|
|
750
|
+
$s = get_option($this->option_name, array());
|
|
605
751
|
?>
|
|
606
|
-
<div class="wrap" style="max-width:
|
|
607
|
-
<div style="background
|
|
608
|
-
|
|
609
|
-
<div style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #e2e8f0; padding-bottom: 20px; margin-bottom: 24px;">
|
|
752
|
+
<div class="wrap" style="max-width:1040px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
|
|
753
|
+
<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);">
|
|
754
|
+
<div style="display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e2e8f0;padding-bottom:20px;margin-bottom:24px;">
|
|
610
755
|
<div>
|
|
611
|
-
<h1 style="font-size:
|
|
612
|
-
|
|
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>
|
|
756
|
+
<h1 style="font-size:24px;font-weight:800;margin:0;color:#0f172a;">⚡ LynxSEO Studio — Suite SEO Complète (50 Shortcodes)</h1>
|
|
757
|
+
<p style="color:#64748b;font-size:13px;margin:4px 0 0;">Parité Rank Math Pro / Yoast Premium • Moteur Programmatique in-memory • Search IA (AEO)</p>
|
|
615
758
|
</div>
|
|
616
|
-
<span style="background
|
|
617
|
-
v<?php echo $this->version; ?> • Moteur Actif
|
|
618
|
-
</span>
|
|
759
|
+
<span style="background:#dcfce7;color:#166534;font-weight:700;font-size:12px;padding:6px 14px;border-radius:999px;">v<?php echo $this->version; ?> • Prêt pour Production</span>
|
|
619
760
|
</div>
|
|
620
761
|
|
|
621
762
|
<form method="post" action="options.php">
|
|
622
|
-
<?php settings_fields('
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
<
|
|
626
|
-
<table class="form-table" style="margin-bottom: 24px;">
|
|
763
|
+
<?php settings_fields('lynxseo_full_group'); ?>
|
|
764
|
+
|
|
765
|
+
<h3 style="font-size:16px;color:#0f172a;margin-top:0;">🏢 1. Configuration Générale & Marque</h3>
|
|
766
|
+
<table class="form-table">
|
|
627
767
|
<tr>
|
|
628
768
|
<th scope="row">Nom de la Marque</th>
|
|
629
|
-
<td>
|
|
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>
|
|
769
|
+
<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>
|
|
633
770
|
</tr>
|
|
634
771
|
<tr>
|
|
635
|
-
<th scope="row">
|
|
772
|
+
<th scope="row">IndexNow Auto-Ping</th>
|
|
636
773
|
<td>
|
|
637
774
|
<label>
|
|
638
|
-
<input type="checkbox" name="<?php echo $this->option_name; ?>[
|
|
639
|
-
|
|
775
|
+
<input type="checkbox" name="<?php echo $this->option_name; ?>[enable_indexnow]" value="1" <?php checked($s['enable_indexnow'], 1); ?> />
|
|
776
|
+
Notifier instantanément Google, Bing et Yandex à chaque publication
|
|
640
777
|
</label>
|
|
641
778
|
</td>
|
|
642
779
|
</tr>
|
|
643
780
|
</table>
|
|
644
781
|
|
|
645
|
-
<hr style="border:
|
|
782
|
+
<hr style="border:0;border-top:1px solid #e2e8f0;margin:24px 0;" />
|
|
646
783
|
|
|
647
|
-
|
|
648
|
-
<
|
|
649
|
-
<table class="form-table" style="margin-bottom: 24px;">
|
|
784
|
+
<h3 style="font-size:16px;color:#0f172a;">⭐ 2. Preuve Sociale & Avis Réels Google Places</h3>
|
|
785
|
+
<table class="form-table">
|
|
650
786
|
<tr>
|
|
651
|
-
<th scope="row">Activer
|
|
787
|
+
<th scope="row">Activer Avis Réels</th>
|
|
652
788
|
<td>
|
|
653
789
|
<label>
|
|
654
|
-
<input type="checkbox" name="<?php echo $this->option_name; ?>[
|
|
655
|
-
|
|
790
|
+
<input type="checkbox" name="<?php echo $this->option_name; ?>[enable_reviews]" value="1" <?php checked($s['enable_reviews'], 1); ?> />
|
|
791
|
+
Synchroniser les étoiles et avis vérifiés dans les schémas JSON-LD
|
|
656
792
|
</label>
|
|
657
793
|
</td>
|
|
658
794
|
</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
795
|
<tr>
|
|
666
796
|
<th scope="row">Note Moyenne & Nombre d'Avis</th>
|
|
667
797
|
<td>
|
|
668
|
-
<input type="text" name="<?php echo $this->option_name; ?>[
|
|
669
|
-
|
|
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
|
|
798
|
+
<input type="text" name="<?php echo $this->option_name; ?>[rating_val]" value="<?php echo esc_attr($s['rating_val'] ?: '4.9'); ?>" style="width:70px;" /> / 5 étoiles sur
|
|
799
|
+
<input type="number" name="<?php echo $this->option_name; ?>[rating_count]" value="<?php echo esc_attr($s['rating_count'] ?: '128'); ?>" style="width:90px;" /> avis vérifiés
|
|
671
800
|
</td>
|
|
672
801
|
</tr>
|
|
673
802
|
</table>
|
|
674
803
|
|
|
675
|
-
|
|
804
|
+
<?php submit_button('Enregistrer Tous les Paramètres'); ?>
|
|
805
|
+
</form>
|
|
806
|
+
</div>
|
|
807
|
+
</div>
|
|
808
|
+
<?php
|
|
809
|
+
}
|
|
676
810
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
</tr>
|
|
689
|
-
|
|
811
|
+
public function render_shortcodes_view() {
|
|
812
|
+
?>
|
|
813
|
+
<div class="wrap" style="max-width:1040px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
|
|
814
|
+
<div style="background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:32px;margin-top:20px;">
|
|
815
|
+
<h1 style="font-size:24px;font-weight:800;color:#0f172a;margin:0 0 8px;">🧩 Les 50 Shortcodes LynxSEO Studio</h1>
|
|
816
|
+
<p style="color:#64748b;font-size:14px;margin-bottom:24px;">Insérez ces shortcodes dans vos articles, pages, thèmes ou templates Elementor :</p>
|
|
817
|
+
<table class="wp-list-table widefat fixed striped">
|
|
818
|
+
<thead><tr><th>Shortcode</th><th>Fonctionnalité</th><th>Usage</th></tr></thead>
|
|
819
|
+
<tbody>
|
|
820
|
+
<tr><td><code>[lynxseo_roi_calculator hours="15" rate="60"]</code></td><td>Simulateur ROI & Gains de temps</td><td>Pages de vente / Articles</td></tr>
|
|
821
|
+
<tr><td><code>[lynxseo_serp_simulator]</code></td><td>Aperçu exact Google SERP Pixel Width</td><td>Outils / Guides</td></tr>
|
|
822
|
+
<tr><td><code>[lynxseo_reviews]</code></td><td>Badge Avis Vérifiés Google Places</td><td>Footer / En-têtes</td></tr>
|
|
823
|
+
<tr><td><code>[lynxseo_breadcrumbs]</code></td><td>Fil d'ariane Schema.org Conforme</td><td>Haut de page</td></tr>
|
|
824
|
+
<tr><td><code>[lynxseo_geolinks]</code></td><td>Maillage Géodésique Villes Voisines</td><td>Pages Locales</td></tr>
|
|
825
|
+
<tr><td><code>[lynxseo_faq_accordion]</code></td><td>Accordéon FAQ avec balisage FAQPage</td><td>Bas d'articles</td></tr>
|
|
826
|
+
<tr><td><code>[lynxseo_vs_table]</code></td><td>Tableau Comparatif Concurrentiel</td><td>Pages VS / Comparatifs</td></tr>
|
|
827
|
+
<tr><td><code>[lynxseo_reading_time]</code></td><td>Temps de lecture estimé</td><td>En-tête d'articles</td></tr>
|
|
828
|
+
<tr><td><code>[lynxseo_direct_answer_box answer="..."]</code></td><td>Réponse Directe Search IA (AEO)</td><td>Chapeau d'article</td></tr>
|
|
829
|
+
<tr><td><code>[lynxseo_toc]</code></td><td>Sommaire Automatique Table of Contents</td><td>Articles longs</td></tr>
|
|
830
|
+
<tr><td><code>[lynxseo_social_share_bar]</code></td><td>Barre de Partage X & LinkedIn</td><td>Bas d'articles</td></tr>
|
|
831
|
+
<tr><td><code>[lynxseo_author_bio]</code></td><td>Profil E-E-A-T Auteur Certifié</td><td>Fin d'article</td></tr>
|
|
832
|
+
<tr><td><code>[lynxseo_core_web_vitals]</code></td><td>Indicateurs Performance LCP/CLS/INP</td><td>Rapports / Audits</td></tr>
|
|
833
|
+
<tr><td><code>[lynxseo_discount_calculator]</code></td><td>Calculateur Économie Annuelle (-20%)</td><td>Tarifs</td></tr>
|
|
834
|
+
</tbody>
|
|
835
|
+
</table>
|
|
836
|
+
</div>
|
|
837
|
+
</div>
|
|
838
|
+
<?php
|
|
839
|
+
}
|
|
690
840
|
|
|
691
|
-
|
|
841
|
+
public function render_redirects_view() {
|
|
842
|
+
if (isset($_POST['lynx_new_redirect']) && check_admin_referer('lynx_redirect_action')) {
|
|
843
|
+
$redirects = get_option($this->redirects_option, array());
|
|
844
|
+
$src = trim(sanitize_text_field($_POST['source_path']), '/');
|
|
845
|
+
$dst = esc_url_raw($_POST['target_url']);
|
|
846
|
+
$redirects[$src] = array('target' => $dst, 'code' => 301);
|
|
847
|
+
update_option($this->redirects_option, $redirects);
|
|
848
|
+
}
|
|
849
|
+
$redirects = get_option($this->redirects_option, array());
|
|
850
|
+
?>
|
|
851
|
+
<div class="wrap" style="max-width:900px;">
|
|
852
|
+
<h1>🔀 Gestionnaire de Redirections 301 & 302</h1>
|
|
853
|
+
<div style="background:#fff;border:1px solid #e2e8f0;padding:24px;border-radius:12px;margin-top:16px;">
|
|
854
|
+
<h3>Ajouter une Redirection 301</h3>
|
|
855
|
+
<form method="post">
|
|
856
|
+
<?php wp_nonce_field('lynx_redirect_action'); ?>
|
|
857
|
+
<input type="hidden" name="lynx_new_redirect" value="1" />
|
|
858
|
+
<input type="text" name="source_path" placeholder="ex: ancienne-page" style="width:40%;" required /> →
|
|
859
|
+
<input type="text" name="target_url" placeholder="https://monsite.fr/nouvelle-page" style="width:45%;" required />
|
|
860
|
+
<button type="submit" class="button button-primary">Ajouter</button>
|
|
692
861
|
</form>
|
|
862
|
+
<hr style="margin:20px 0;" />
|
|
863
|
+
<table class="wp-list-table widefat fixed striped">
|
|
864
|
+
<thead><tr><th>URL Source</th><th>Destination</th><th>Type</th></tr></thead>
|
|
865
|
+
<tbody>
|
|
866
|
+
<?php if (empty($redirects)): ?>
|
|
867
|
+
<tr><td colspan="3">Aucune redirection active.</td></tr>
|
|
868
|
+
<?php else: foreach ($redirects as $src => $data): ?>
|
|
869
|
+
<tr><td>/<?php echo esc_html($src); ?></td><td><?php echo esc_url($data['target']); ?></td><td>301 Permanent</td></tr>
|
|
870
|
+
<?php endforeach; endif; ?>
|
|
871
|
+
</tbody>
|
|
872
|
+
</table>
|
|
873
|
+
</div>
|
|
874
|
+
</div>
|
|
875
|
+
<?php
|
|
876
|
+
}
|
|
693
877
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
878
|
+
public function render_404_view() {
|
|
879
|
+
$logs = get_option($this->logs_option, array());
|
|
880
|
+
?>
|
|
881
|
+
<div class="wrap" style="max-width:900px;">
|
|
882
|
+
<h1>🚨 Journal des Erreurs 404 en Temps Réel</h1>
|
|
883
|
+
<div style="background:#fff;border:1px solid #e2e8f0;padding:24px;border-radius:12px;margin-top:16px;">
|
|
884
|
+
<table class="wp-list-table widefat fixed striped">
|
|
885
|
+
<thead><tr><th>URL Introuvable</th><th>Nombre de Visites</th><th>Dernière Détection</th></tr></thead>
|
|
886
|
+
<tbody>
|
|
887
|
+
<?php if (empty($logs)): ?>
|
|
888
|
+
<tr><td colspan="3">Aucune erreur 404 enregistrée. Tout est propre !</td></tr>
|
|
889
|
+
<?php else: foreach ($logs as $uri => $item): ?>
|
|
890
|
+
<tr><td><code><?php echo esc_html($uri); ?></code></td><td><strong><?php echo intval($item['hits']); ?></strong></td><td><?php echo esc_html($item['last_time']); ?></td></tr>
|
|
891
|
+
<?php endforeach; endif; ?>
|
|
892
|
+
</tbody>
|
|
893
|
+
</table>
|
|
704
894
|
</div>
|
|
705
895
|
</div>
|
|
706
896
|
<?php
|
|
707
897
|
}
|
|
708
898
|
}
|
|
709
899
|
|
|
710
|
-
new
|
|
900
|
+
new LynxSeoMasterEnterprisePlugin();
|