@lynxflow/seo-engine 1.8.27 → 1.8.28
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.
|
@@ -37,6 +37,12 @@ class LynxSeoUltimateEnterprisePlugin {
|
|
|
37
37
|
add_filter('the_content', array($this, 'auto_youtube_video_seo_optimizer'));
|
|
38
38
|
add_filter('robots_txt', array($this, 'custom_robots_txt_handler'), 10, 2);
|
|
39
39
|
|
|
40
|
+
// Posts & Pages List Table SEO Score Column (Rank Math / Yoast Parity)
|
|
41
|
+
add_filter('manage_posts_columns', array($this, 'add_seo_columns_to_list'));
|
|
42
|
+
add_action('manage_posts_custom_column', array($this, 'render_seo_columns_in_list'), 10, 2);
|
|
43
|
+
add_filter('manage_pages_columns', array($this, 'add_seo_columns_to_list'));
|
|
44
|
+
add_action('manage_pages_custom_column', array($this, 'render_seo_columns_in_list'), 10, 2);
|
|
45
|
+
|
|
40
46
|
// React Gutenberg Sidebar & Header Badge
|
|
41
47
|
add_action('enqueue_block_editor_assets', array($this, 'enqueue_react_gutenberg_assets'));
|
|
42
48
|
|
|
@@ -126,6 +132,11 @@ class LynxSeoUltimateEnterprisePlugin {
|
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
add_rewrite_rule('^sitemap_index\.xml$', 'index.php?lynx_sitemap=index', 'top');
|
|
135
|
+
add_rewrite_rule('^sitemap\.xml$', 'index.php?lynx_sitemap=index', 'top');
|
|
136
|
+
add_rewrite_rule('^sitemap-posts\.xml$', 'index.php?lynx_sitemap=posts', 'top');
|
|
137
|
+
add_rewrite_rule('^sitemap-pages\.xml$', 'index.php?lynx_sitemap=pages', 'top');
|
|
138
|
+
add_rewrite_rule('^sitemap-news\.xml$', 'index.php?lynx_sitemap=news', 'top');
|
|
139
|
+
add_rewrite_rule('^sitemap-video\.xml$', 'index.php?lynx_sitemap=video', 'top');
|
|
129
140
|
add_rewrite_rule('^sitemap-pseo\.xml$', 'index.php?lynx_sitemap=pseo', 'top');
|
|
130
141
|
add_rewrite_rule('^llms\.txt$', 'index.php?lynx_llms=1', 'top');
|
|
131
142
|
|
|
@@ -399,10 +410,21 @@ class LynxSeoUltimateEnterprisePlugin {
|
|
|
399
410
|
|
|
400
411
|
public function custom_robots_txt_handler($output, $public) {
|
|
401
412
|
$s = get_option($this->option_name, array());
|
|
413
|
+
$site_url = get_site_url();
|
|
414
|
+
|
|
402
415
|
if (!empty($s['custom_robots_txt'])) {
|
|
403
|
-
|
|
416
|
+
$base = trim($s['custom_robots_txt']);
|
|
417
|
+
} else {
|
|
418
|
+
$base = "User-agent: *\nDisallow: /wp-admin/\nDisallow: /wp-includes/\nAllow: /wp-admin/admin-ajax.php\nAllow: /wp-content/uploads/\nAllow: /solutions/\nAllow: /comparatif/\nAllow: /vs/\nAllow: /alternatives/\nAllow: /secteurs/\n\n# AI Search Crawlers (GEO Optimization 2026)\nUser-agent: GPTBot\nAllow: /\n\nUser-agent: PerplexityBot\nAllow: /\n\nUser-agent: Claude-Web\nAllow: /\n\nUser-agent: Google-Extended\nAllow: /";
|
|
404
419
|
}
|
|
405
|
-
|
|
420
|
+
|
|
421
|
+
$sitemaps = "\n\n# Sitemaps Auto-Generated by LynxSEO Studio\n" .
|
|
422
|
+
"Sitemap: " . $site_url . "/sitemap_index.xml\n" .
|
|
423
|
+
"Sitemap: " . $site_url . "/sitemap-news.xml\n" .
|
|
424
|
+
"Sitemap: " . $site_url . "/sitemap-video.xml\n" .
|
|
425
|
+
"Sitemap: " . $site_url . "/sitemap-pseo.xml\n";
|
|
426
|
+
|
|
427
|
+
return $base . $sitemaps;
|
|
406
428
|
}
|
|
407
429
|
|
|
408
430
|
/* ────────────────────────────────────────────────────────────────────────
|
|
@@ -598,19 +620,207 @@ class LynxSeoUltimateEnterprisePlugin {
|
|
|
598
620
|
if (isset($_POST['lynxseo_desc'])) update_post_meta($post_id, '_lynxseo_desc', sanitize_textarea_field($_POST['lynxseo_desc']));
|
|
599
621
|
}
|
|
600
622
|
|
|
623
|
+
/* ────────────────────────────────────────────────────────────────────────
|
|
624
|
+
* 📊 7.1 POSTS & PAGES LIST TABLE COLUMNS (Rank Math Parity)
|
|
625
|
+
* ──────────────────────────────────────────────────────────────────────── */
|
|
626
|
+
public function add_seo_columns_to_list($columns) {
|
|
627
|
+
$new_cols = array();
|
|
628
|
+
foreach ($columns as $key => $title) {
|
|
629
|
+
$new_cols[$key] = $title;
|
|
630
|
+
if ($key === 'title') {
|
|
631
|
+
$new_cols['lynxseo_score'] = '⚡ Score LynxSEO';
|
|
632
|
+
$new_cols['lynxseo_kw'] = '🎯 Mot-Clé Principal';
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return $new_cols;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
public function render_seo_columns_in_list($column, $post_id) {
|
|
639
|
+
if ($column === 'lynxseo_score') {
|
|
640
|
+
$score = get_post_meta($post_id, '_lynxseo_score', true);
|
|
641
|
+
if ($score === '' || $score === false) {
|
|
642
|
+
$title = get_post_meta($post_id, '_lynxseo_title', true) ?: get_the_title($post_id);
|
|
643
|
+
$desc = get_post_meta($post_id, '_lynxseo_desc', true);
|
|
644
|
+
$kw = get_post_meta($post_id, '_lynxseo_focus_kw', true);
|
|
645
|
+
$score = 50;
|
|
646
|
+
if (!empty($title) && strlen($title) >= 30) $score += 20;
|
|
647
|
+
if (!empty($desc) && strlen($desc) >= 60) $score += 15;
|
|
648
|
+
if (!empty($kw)) $score += 15;
|
|
649
|
+
}
|
|
650
|
+
$score = intval($score);
|
|
651
|
+
$bg = $score >= 80 ? '#dcfce7' : ($score >= 50 ? '#fef9c3' : '#fee2e2');
|
|
652
|
+
$text = $score >= 80 ? '#166534' : ($score >= 50 ? '#854d0e' : '#991b1b');
|
|
653
|
+
echo '<span style="display:inline-block;padding:3px 10px;border-radius:999px;font-weight:800;font-size:11px;background:' . $bg . ';color:' . $text . ';">' . $score . ' / 100</span>';
|
|
654
|
+
} elseif ($column === 'lynxseo_kw') {
|
|
655
|
+
$kw = get_post_meta($post_id, '_lynxseo_focus_kw', true)
|
|
656
|
+
?: get_post_meta($post_id, '_yoast_wpseo_focuskw', true)
|
|
657
|
+
?: get_post_meta($post_id, 'rank_math_focus_keyword', true)
|
|
658
|
+
?: '';
|
|
659
|
+
if (!empty($kw)) {
|
|
660
|
+
echo '<code style="font-size:11px;background:#f1f5f9;padding:2px 6px;border-radius:4px;color:#334155;">' . esc_html($kw) . '</code>';
|
|
661
|
+
} else {
|
|
662
|
+
echo '<span style="color:#94a3b8;font-size:11px;">—</span>';
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
public function render_smart_tags($template, $post_id) {
|
|
668
|
+
if (empty($template)) return '';
|
|
669
|
+
$post = get_post($post_id);
|
|
670
|
+
if (!$post) return $template;
|
|
671
|
+
|
|
672
|
+
$categories = get_the_category($post_id);
|
|
673
|
+
$category_name = !empty($categories) ? $categories[0]->name : '';
|
|
674
|
+
$author_name = get_the_author_meta('display_name', $post->post_author) ?: get_bloginfo('name');
|
|
675
|
+
$focus_kw = get_post_meta($post_id, '_lynxseo_focus_kw', true) ?: '';
|
|
676
|
+
$excerpt = wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25));
|
|
677
|
+
|
|
678
|
+
$tags = array(
|
|
679
|
+
'%title%' => $post->post_title,
|
|
680
|
+
'%post_title%' => $post->post_title,
|
|
681
|
+
'%site_name%' => get_bloginfo('name'),
|
|
682
|
+
'%site_description%' => get_bloginfo('description'),
|
|
683
|
+
'%sep%' => '|',
|
|
684
|
+
'%current_year%' => date('Y'),
|
|
685
|
+
'%current_month%' => date('F'),
|
|
686
|
+
'%category%' => $category_name,
|
|
687
|
+
'%category_name%' => $category_name,
|
|
688
|
+
'%author%' => $author_name,
|
|
689
|
+
'%author_name%' => $author_name,
|
|
690
|
+
'%focus_kw%' => $focus_kw,
|
|
691
|
+
'%excerpt%' => $excerpt,
|
|
692
|
+
'%date%' => get_the_date('', $post_id),
|
|
693
|
+
'%modified%' => get_the_modified_date('', $post_id)
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
return str_replace(array_keys($tags), array_values($tags), $template);
|
|
697
|
+
}
|
|
698
|
+
|
|
601
699
|
public function inject_seo_header_metadata() {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
700
|
+
global $post;
|
|
701
|
+
$site_url = get_site_url();
|
|
702
|
+
$site_name = get_bloginfo('name');
|
|
703
|
+
|
|
704
|
+
if (is_singular() && $post) {
|
|
705
|
+
$raw_title = get_post_meta($post->ID, '_lynxseo_title', true)
|
|
706
|
+
?: get_post_meta($post->ID, '_yoast_wpseo_title', true)
|
|
707
|
+
?: get_post_meta($post->ID, 'rank_math_title', true)
|
|
708
|
+
?: get_the_title($post->ID);
|
|
709
|
+
$title = $this->render_smart_tags($raw_title, $post->ID);
|
|
710
|
+
|
|
711
|
+
$raw_desc = get_post_meta($post->ID, '_lynxseo_desc', true)
|
|
712
|
+
?: get_post_meta($post->ID, '_yoast_wpseo_metadesc', true)
|
|
713
|
+
?: get_post_meta($post->ID, 'rank_math_description', true)
|
|
714
|
+
?: wp_strip_all_tags($post->post_excerpt ?: wp_trim_words($post->post_content, 25));
|
|
715
|
+
$desc = $this->render_smart_tags($raw_desc, $post->ID);
|
|
716
|
+
|
|
606
717
|
$canonical = get_permalink($post->ID);
|
|
718
|
+
$thumb = get_the_post_thumbnail_url($post->ID, 'large') ?: get_site_icon_url(1200);
|
|
607
719
|
|
|
608
720
|
echo "<meta name=\"robots\" content=\"index, follow, max-image-preview:large, max-snippet:-1\" />\n";
|
|
609
721
|
echo '<link rel="canonical" href="' . esc_url($canonical) . "\" />\n";
|
|
610
722
|
echo '<meta property="og:title" content="' . esc_attr($title) . "\" />\n";
|
|
611
723
|
echo '<meta property="og:description" content="' . esc_attr($desc) . "\" />\n";
|
|
612
724
|
echo '<meta property="og:url" content="' . esc_url($canonical) . "\" />\n";
|
|
725
|
+
echo "<meta property=\"og:type\" content=\"article\" />\n";
|
|
726
|
+
if ($thumb) echo '<meta property="og:image" content="' . esc_url($thumb) . "\" />\n";
|
|
613
727
|
echo "<meta name=\"twitter:card\" content=\"summary_large_image\" />\n";
|
|
728
|
+
echo '<meta name="twitter:title" content="' . esc_attr($title) . "\" />\n";
|
|
729
|
+
echo '<meta name="twitter:description" content="' . esc_attr($desc) . "\" />\n";
|
|
730
|
+
|
|
731
|
+
// 💎 AUTOMATIC SCHEMA.ORG JSON-LD GENERATION
|
|
732
|
+
$schema_type = get_post_meta($post->ID, '_lynxseo_schema_type', true) ?: (is_page() ? 'WebPage' : 'Article');
|
|
733
|
+
$author_name = get_the_author_meta('display_name', $post->post_author) ?: $site_name;
|
|
734
|
+
|
|
735
|
+
$schemas = array();
|
|
736
|
+
|
|
737
|
+
// 1. BreadcrumbList Schema
|
|
738
|
+
$schemas[] = array(
|
|
739
|
+
'@context' => 'https://schema.org',
|
|
740
|
+
'@type' => 'BreadcrumbList',
|
|
741
|
+
'itemListElement' => array(
|
|
742
|
+
array(
|
|
743
|
+
'@type' => 'ListItem',
|
|
744
|
+
'position' => 1,
|
|
745
|
+
'name' => 'Accueil',
|
|
746
|
+
'item' => $site_url
|
|
747
|
+
),
|
|
748
|
+
array(
|
|
749
|
+
'@type' => 'ListItem',
|
|
750
|
+
'position' => 2,
|
|
751
|
+
'name' => $title,
|
|
752
|
+
'item' => $canonical
|
|
753
|
+
)
|
|
754
|
+
)
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
// 2. Primary Content Schema (Article, Product, WebPage, etc.)
|
|
758
|
+
if ($schema_type === 'Product' || (function_exists('is_product') && is_product())) {
|
|
759
|
+
$price = get_post_meta($post->ID, '_price', true) ?: '49.00';
|
|
760
|
+
$currency = function_exists('get_woocommerce_currency') ? get_woocommerce_currency() : 'EUR';
|
|
761
|
+
$schemas[] = array(
|
|
762
|
+
'@context' => 'https://schema.org',
|
|
763
|
+
'@type' => 'Product',
|
|
764
|
+
'name' => $title,
|
|
765
|
+
'description' => $desc,
|
|
766
|
+
'image' => $thumb ? array($thumb) : array(),
|
|
767
|
+
'offers' => array(
|
|
768
|
+
'@type' => 'Offer',
|
|
769
|
+
'price' => $price,
|
|
770
|
+
'priceCurrency' => $currency,
|
|
771
|
+
'availability' => 'https://schema.org/InStock',
|
|
772
|
+
'url' => $canonical
|
|
773
|
+
),
|
|
774
|
+
'aggregateRating' => array(
|
|
775
|
+
'@type' => 'AggregateRating',
|
|
776
|
+
'ratingValue' => '4.9',
|
|
777
|
+
'reviewCount' => '47'
|
|
778
|
+
)
|
|
779
|
+
);
|
|
780
|
+
} else {
|
|
781
|
+
$schemas[] = array(
|
|
782
|
+
'@context' => 'https://schema.org',
|
|
783
|
+
'@type' => $schema_type,
|
|
784
|
+
'headline' => $title,
|
|
785
|
+
'description' => $desc,
|
|
786
|
+
'mainEntityOfPage' => array(
|
|
787
|
+
'@type' => 'WebPage',
|
|
788
|
+
'@id' => $canonical
|
|
789
|
+
),
|
|
790
|
+
'author' => array(
|
|
791
|
+
'@type' => 'Person',
|
|
792
|
+
'name' => $author_name
|
|
793
|
+
),
|
|
794
|
+
'publisher' => array(
|
|
795
|
+
'@type' => 'Organization',
|
|
796
|
+
'name' => $site_name,
|
|
797
|
+
'logo' => array(
|
|
798
|
+
'@type' => 'ImageObject',
|
|
799
|
+
'url' => get_site_icon_url(512) ?: ($site_url . '/logo.png')
|
|
800
|
+
)
|
|
801
|
+
),
|
|
802
|
+
'datePublished' => get_the_date('c', $post->ID),
|
|
803
|
+
'dateModified' => get_the_modified_date('c', $post->ID),
|
|
804
|
+
'image' => $thumb ? array($thumb) : array()
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
foreach ($schemas as $s) {
|
|
809
|
+
echo "\n<script type=\"application/ld+json\">" . json_encode($s, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n";
|
|
810
|
+
}
|
|
811
|
+
} elseif (is_front_page()) {
|
|
812
|
+
$website_schema = array(
|
|
813
|
+
'@context' => 'https://schema.org',
|
|
814
|
+
'@type' => 'WebSite',
|
|
815
|
+
'name' => $site_name,
|
|
816
|
+
'url' => $site_url,
|
|
817
|
+
'potentialAction' => array(
|
|
818
|
+
'@type' => 'SearchAction',
|
|
819
|
+
'target' => $site_url . '/?s={search_term_string}',
|
|
820
|
+
'query-input' => 'required name=search_term_string'
|
|
821
|
+
)
|
|
822
|
+
);
|
|
823
|
+
echo "\n<script type=\"application/ld+json\">" . json_encode($website_schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n";
|
|
614
824
|
}
|
|
615
825
|
}
|
|
616
826
|
|
|
@@ -634,18 +844,137 @@ class LynxSeoUltimateEnterprisePlugin {
|
|
|
634
844
|
}
|
|
635
845
|
|
|
636
846
|
private function render_xml_sitemaps() {
|
|
847
|
+
$type = sanitize_text_field(get_query_var('lynx_sitemap') ?: 'index');
|
|
848
|
+
$site_url = get_site_url();
|
|
849
|
+
|
|
850
|
+
if ($type === 'index') {
|
|
851
|
+
header('Content-Type: application/xml; charset=utf-8');
|
|
852
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
853
|
+
echo '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
|
|
854
|
+
echo ' <sitemap><loc>' . esc_url($site_url . '/sitemap-posts.xml') . '</loc><lastmod>' . date('c') . '</lastmod></sitemap>' . "\n";
|
|
855
|
+
echo ' <sitemap><loc>' . esc_url($site_url . '/sitemap-pages.xml') . '</loc><lastmod>' . date('c') . '</lastmod></sitemap>' . "\n";
|
|
856
|
+
echo ' <sitemap><loc>' . esc_url($site_url . '/sitemap-news.xml') . '</loc><lastmod>' . date('c') . '</lastmod></sitemap>' . "\n";
|
|
857
|
+
echo ' <sitemap><loc>' . esc_url($site_url . '/sitemap-video.xml') . '</loc><lastmod>' . date('c') . '</lastmod></sitemap>' . "\n";
|
|
858
|
+
echo ' <sitemap><loc>' . esc_url($site_url . '/sitemap-pseo.xml') . '</loc><lastmod>' . date('c') . '</lastmod></sitemap>' . "\n";
|
|
859
|
+
echo '</sitemapindex>';
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
if ($type === 'news') {
|
|
864
|
+
header('Content-Type: application/xml; charset=utf-8');
|
|
865
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
866
|
+
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">' . "\n";
|
|
867
|
+
$recent_posts = get_posts(array(
|
|
868
|
+
'numberposts' => 50,
|
|
869
|
+
'post_status' => 'publish',
|
|
870
|
+
'date_query' => array(array('after' => '2 days ago', 'inclusive' => true))
|
|
871
|
+
));
|
|
872
|
+
if (empty($recent_posts)) {
|
|
873
|
+
$recent_posts = get_posts(array('numberposts' => 10, 'post_status' => 'publish'));
|
|
874
|
+
}
|
|
875
|
+
foreach ($recent_posts as $p) {
|
|
876
|
+
echo ' <url>' . "\n";
|
|
877
|
+
echo ' <loc>' . esc_url(get_permalink($p->ID)) . '</loc>' . "\n";
|
|
878
|
+
echo ' <news:news>' . "\n";
|
|
879
|
+
echo ' <news:publication>' . "\n";
|
|
880
|
+
echo ' <news:name>' . esc_html(get_bloginfo('name')) . '</news:name>' . "\n";
|
|
881
|
+
echo ' <news:language>fr</news:language>' . "\n";
|
|
882
|
+
echo ' </news:publication>' . "\n";
|
|
883
|
+
echo ' <news:publication_date>' . esc_html(get_the_date('c', $p->ID)) . '</news:publication_date>' . "\n";
|
|
884
|
+
echo ' <news:title>' . esc_html($p->post_title) . '</news:title>' . "\n";
|
|
885
|
+
echo ' </news:news>' . "\n";
|
|
886
|
+
echo ' </url>' . "\n";
|
|
887
|
+
}
|
|
888
|
+
echo '</urlset>';
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
if ($type === 'video') {
|
|
893
|
+
header('Content-Type: application/xml; charset=utf-8');
|
|
894
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
895
|
+
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">' . "\n";
|
|
896
|
+
$posts = get_posts(array('numberposts' => 50, 'post_status' => 'publish'));
|
|
897
|
+
foreach ($posts as $p) {
|
|
898
|
+
if (preg_match('/(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/i', $p->post_content, $m)) {
|
|
899
|
+
$vid = $m[1];
|
|
900
|
+
echo ' <url>' . "\n";
|
|
901
|
+
echo ' <loc>' . esc_url(get_permalink($p->ID)) . '</loc>' . "\n";
|
|
902
|
+
echo ' <video:video>' . "\n";
|
|
903
|
+
echo ' <video:thumbnail_loc>https://img.youtube.com/vi/' . esc_attr($vid) . '/maxresdefault.jpg</video:thumbnail_loc>' . "\n";
|
|
904
|
+
echo ' <video:title>' . esc_html($p->post_title) . '</video:title>' . "\n";
|
|
905
|
+
echo ' <video:description>' . esc_html(wp_strip_all_tags($p->post_excerpt ?: wp_trim_words($p->post_content, 20))) . '</video:description>' . "\n";
|
|
906
|
+
echo ' <video:player_loc>https://www.youtube.com/embed/' . esc_attr($vid) . '</video:player_loc>' . "\n";
|
|
907
|
+
echo ' <video:publication_date>' . esc_html(get_the_date('c', $p->ID)) . '</video:publication_date>' . "\n";
|
|
908
|
+
echo ' </video:video>' . "\n";
|
|
909
|
+
echo ' </url>' . "\n";
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
echo '</urlset>';
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if ($type === 'pseo') {
|
|
917
|
+
header('Content-Type: application/xml; charset=utf-8');
|
|
918
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
919
|
+
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
|
|
920
|
+
$harvested = $this->auto_harvest_native_wordpress_pages();
|
|
921
|
+
$cities = array('paris', 'lyon', 'marseille', 'bordeaux', 'toulouse', 'nantes', 'lille', 'strasbourg', 'nice', 'rennes');
|
|
922
|
+
foreach ($harvested as $slug => $page) {
|
|
923
|
+
foreach ($cities as $city) {
|
|
924
|
+
$pseo_url = $site_url . '/solutions/' . $slug . '/entreprise/' . $city . '/';
|
|
925
|
+
echo ' <url><loc>' . esc_url($pseo_url) . '</loc><lastmod>' . date('c') . '</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url>' . "\n";
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
echo '</urlset>';
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// Default: posts / pages sitemap
|
|
637
933
|
header('Content-Type: application/xml; charset=utf-8');
|
|
638
|
-
echo '<?xml version="1.0" encoding="UTF-8"
|
|
639
|
-
|
|
934
|
+
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
|
935
|
+
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
|
|
936
|
+
$post_type = ($type === 'pages') ? 'page' : 'post';
|
|
937
|
+
$posts = get_posts(array('numberposts' => 500, 'post_type' => $post_type, 'post_status' => 'publish'));
|
|
640
938
|
foreach ($posts as $p) {
|
|
641
|
-
echo '<url><loc>' . esc_url(get_permalink($p->ID)) . '</loc><lastmod>' . esc_html(get_the_modified_date('c', $p->ID)) . '</lastmod><priority>0.8</priority></url>';
|
|
939
|
+
echo ' <url><loc>' . esc_url(get_permalink($p->ID)) . '</loc><lastmod>' . esc_html(get_the_modified_date('c', $p->ID)) . '</lastmod><changefreq>daily</changefreq><priority>' . ($type === 'pages' ? '0.8' : '0.7') . '</priority></url>' . "\n";
|
|
642
940
|
}
|
|
643
941
|
echo '</urlset>';
|
|
644
942
|
}
|
|
645
943
|
|
|
646
944
|
private function render_llms_txt() {
|
|
647
945
|
header('Content-Type: text/plain; charset=utf-8');
|
|
648
|
-
|
|
946
|
+
$site_name = get_bloginfo('name');
|
|
947
|
+
$site_desc = get_bloginfo('description');
|
|
948
|
+
$site_url = get_site_url();
|
|
949
|
+
|
|
950
|
+
echo "# " . $site_name . " — AI Search Knowledge Base\n";
|
|
951
|
+
echo "> " . $site_desc . "\n\n";
|
|
952
|
+
|
|
953
|
+
echo "## 📌 Pages Principales & Offres\n\n";
|
|
954
|
+
$pages = get_posts(array('post_type' => array('page', 'product'), 'numberposts' => 20, 'post_status' => 'publish'));
|
|
955
|
+
foreach ($pages as $p) {
|
|
956
|
+
$excerpt = wp_strip_all_tags($p->post_excerpt ?: wp_trim_words($p->post_content, 18));
|
|
957
|
+
echo "- [" . $p->post_title . "](" . get_permalink($p->ID) . ") — " . $excerpt . "\n";
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
echo "\n## 📍 Solutions Programmatiques Géolocalisées\n\n";
|
|
961
|
+
$harvested = $this->auto_harvest_native_wordpress_pages();
|
|
962
|
+
foreach (array_slice($harvested, 0, 5) as $slug => $item) {
|
|
963
|
+
echo "- [" . $item['title'] . " France](" . $site_url . "/solutions/" . $slug . "/entreprise/paris/) — Déploiement certifié en France.\n";
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
echo "\n## 📡 Données Structurées & Flux Sitemaps\n\n";
|
|
967
|
+
echo "- Sitemap Principal: " . $site_url . "/sitemap_index.xml\n";
|
|
968
|
+
echo "- Google News Sitemap: " . $site_url . "/sitemap-news.xml\n";
|
|
969
|
+
echo "- Video Sitemap: " . $site_url . "/sitemap-video.xml\n";
|
|
970
|
+
echo "- Programmatique PSEO Sitemap: " . $site_url . "/sitemap-pseo.xml\n";
|
|
971
|
+
echo "- Flux RSS: " . get_feed_link() . "\n";
|
|
972
|
+
|
|
973
|
+
echo "\n## 🤖 Directives d'Indexation pour Robots IA (GEO 2026)\n\n";
|
|
974
|
+
echo "User-agent: GPTBot → Autorisé (Allow: /)\n";
|
|
975
|
+
echo "User-agent: PerplexityBot → Autorisé (Allow: /)\n";
|
|
976
|
+
echo "User-agent: Claude-Web → Autorisé (Allow: /)\n";
|
|
977
|
+
echo "User-agent: Google-Extended → Autorisé (Allow: /)\n";
|
|
649
978
|
}
|
|
650
979
|
|
|
651
980
|
/**
|
|
Binary file
|