@lynxflow/seo-engine 1.8.30 → 2.0.0
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.
- package/README.md +47 -93
- package/dist/ai-copilot-client.d.ts +2 -0
- package/dist/built-in-locations.d.ts +18 -0
- package/dist/content-ai-arsenal.d.ts +28 -0
- package/dist/existing-media-harvester.d.ts +33 -0
- package/dist/extended-schemas.d.ts +84 -0
- package/dist/features-knowledge-harvester.d.ts +56 -0
- package/dist/geo-citation-scorer.d.ts +34 -0
- package/dist/i18n-detector.d.ts +1 -1
- package/dist/index.d.ts +32 -7
- package/dist/index.js +538 -82
- package/dist/index.mjs +2028 -163
- package/dist/internal-pagerank-graph.d.ts +59 -0
- package/dist/knowledge-bank-builder.d.ts +91 -0
- package/dist/marketing-skills-engine.d.ts +74 -0
- package/dist/matrix-engine.d.ts +26 -0
- package/dist/power-words-psychology.d.ts +27 -15
- package/dist/public-manifest-engine.d.ts +58 -0
- package/dist/rag-knowledge-engine.d.ts +50 -0
- package/dist/rate-limited-translator.d.ts +19 -0
- package/dist/token-quota-manager.d.ts +4 -0
- package/package.json +11 -3
- package/TUTORIEL_INTEGRATION_SITE.md +0 -283
- package/connectors/cloudflare-worker/worker.js +0 -106
- package/connectors/laravel/LynxSeoController.php +0 -37
- package/connectors/wordpress/lynxseo-admin-app.js +0 -2611
- package/connectors/wordpress/lynxseo-connector.php +0 -1712
- package/connectors/wordpress/lynxseo-connector.zip +0 -0
- package/lynxflow-seo-engine-1.2.0.tgz +0 -0
- package/src/ad-intelligence-cro.ts +0 -140
- package/src/ai-bots-log-analyzer.ts +0 -127
- package/src/ai-copilot-client.ts +0 -99
- package/src/analytics-client.ts +0 -315
- package/src/auth-key.ts +0 -262
- package/src/backlinks-client.ts +0 -85
- package/src/brand-dna-calendar.ts +0 -120
- package/src/brand-icons.ts +0 -138
- package/src/built-in-locations.ts +0 -170
- package/src/content-ai-arsenal.ts +0 -268
- package/src/copy-frameworks-master.ts +0 -89
- package/src/cro-copywriting-engine.ts +0 -105
- package/src/crosslink-scorer.ts +0 -101
- package/src/embeddable-seo-widget.ts +0 -57
- package/src/engine.test.ts +0 -386
- package/src/engine.ts +0 -813
- package/src/existing-media-harvester.ts +0 -98
- package/src/extended-schemas.ts +0 -589
- package/src/features-knowledge-harvester.ts +0 -190
- package/src/free-public-tools.ts +0 -224
- package/src/geo-mesh-linking.ts +0 -93
- package/src/google-business-profile.ts +0 -280
- package/src/i18n-detector.ts +0 -98
- package/src/i18n-dictionary.ts +0 -422
- package/src/index.ts +0 -164
- package/src/indexnow-client.ts +0 -94
- package/src/instant-matrix-search.ts +0 -48
- package/src/isr-cache-manager.ts +0 -78
- package/src/keyword-permutator.ts +0 -118
- package/src/knowledge-bank-builder.ts +0 -299
- package/src/knowledge-graph-linker.ts +0 -81
- package/src/lago-token-meter.ts +0 -120
- package/src/legal-disclaimers.ts +0 -407
- package/src/llm-content-cleaner.ts +0 -64
- package/src/llm-prompt.ts +0 -323
- package/src/master-marketing-engine.ts +0 -314
- package/src/matrix-engine.ts +0 -1204
- package/src/mcp-seo-server.ts +0 -108
- package/src/ngram-density-analyzer.ts +0 -108
- package/src/og-image-generator.ts +0 -109
- package/src/power-words-psychology.ts +0 -369
- package/src/public-manifest-engine.ts +0 -109
- package/src/rag-knowledge-engine.ts +0 -163
- package/src/rank-math-parity.ts +0 -235
- package/src/rate-limited-translator.ts +0 -110
- package/src/real-reviews-sync.ts +0 -207
- package/src/rss-syndication-feed.ts +0 -56
- package/src/schema-builder.ts +0 -134
- package/src/seo-opportunities-decay.ts +0 -154
- package/src/serp-client.ts +0 -89
- package/src/serp-history-alerts.ts +0 -75
- package/src/site-auditor.ts +0 -83
- package/src/site-crawler.ts +0 -406
- package/src/slug-engine.ts +0 -183
- package/src/social-ads-seo.ts +0 -211
- package/src/social-growth-suite.ts +0 -310
- package/src/social-trend-seo.ts +0 -103
- package/src/social-video-seo.ts +0 -100
- package/src/team-rbac.ts +0 -61
- package/src/technical-rules-auditor.ts +0 -171
- package/src/token-quota-manager.ts +0 -91
- package/src/types.ts +0 -143
- package/src/ui-icons.ts +0 -134
- package/src/urlytics-engine.ts +0 -97
- package/src/video-youtube-analyzer.ts +0 -81
- package/src/yoast-parity.ts +0 -161
- package/tsconfig.json +0 -15
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// src/token-quota-manager.ts
|
|
2
2
|
class TokenQuotaManager {
|
|
3
3
|
tier;
|
|
4
4
|
monthlyCreditBudget;
|
|
@@ -35,6 +35,11 @@ class TokenQuotaManager {
|
|
|
35
35
|
timestamp: new Date().toISOString()
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
+
consume(tokens, model = "openrouter/auto") {
|
|
39
|
+
const prompt = Math.floor(tokens * 0.6);
|
|
40
|
+
const completion = tokens - prompt;
|
|
41
|
+
return this.consumeTokens(prompt, completion, model);
|
|
42
|
+
}
|
|
38
43
|
getStatus() {
|
|
39
44
|
return {
|
|
40
45
|
tier: this.tier,
|
|
@@ -46,7 +51,7 @@ class TokenQuotaManager {
|
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
//
|
|
54
|
+
// src/auth-key.ts
|
|
50
55
|
class ApiKeyGuardian {
|
|
51
56
|
static domainRegistry = new Map;
|
|
52
57
|
static uniquePageRegistry = new Map;
|
|
@@ -220,7 +225,7 @@ class ApiKeyGuardian {
|
|
|
220
225
|
}
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
//
|
|
228
|
+
// src/i18n-dictionary.ts
|
|
224
229
|
var DICTIONARIES = {
|
|
225
230
|
fr: {
|
|
226
231
|
geoTitle: (s, city, country, b) => `${s} à ${city} (${country}) — ${b}`,
|
|
@@ -576,7 +581,7 @@ function isSupportedLanguage(lang) {
|
|
|
576
581
|
return Boolean(DICTIONARIES[code]);
|
|
577
582
|
}
|
|
578
583
|
|
|
579
|
-
//
|
|
584
|
+
// src/indexnow-client.ts
|
|
580
585
|
var SUCCESS_STATUSES = new Set([200, 202]);
|
|
581
586
|
var MAX_URLS_PER_REQUEST = 1e4;
|
|
582
587
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
@@ -632,7 +637,7 @@ class IndexNowClient {
|
|
|
632
637
|
}
|
|
633
638
|
}
|
|
634
639
|
|
|
635
|
-
//
|
|
640
|
+
// src/analytics-client.ts
|
|
636
641
|
class LynxAnalyticsClient {
|
|
637
642
|
apiKey;
|
|
638
643
|
endpoint;
|
|
@@ -861,7 +866,7 @@ class LynxAnalyticsClient {
|
|
|
861
866
|
}
|
|
862
867
|
}
|
|
863
868
|
|
|
864
|
-
//
|
|
869
|
+
// src/serp-client.ts
|
|
865
870
|
class SerpClient {
|
|
866
871
|
apiKey;
|
|
867
872
|
endpoint;
|
|
@@ -914,7 +919,7 @@ class SerpClient {
|
|
|
914
919
|
}
|
|
915
920
|
}
|
|
916
921
|
|
|
917
|
-
//
|
|
922
|
+
// src/backlinks-client.ts
|
|
918
923
|
class BacklinksClient {
|
|
919
924
|
apiKey;
|
|
920
925
|
endpoint;
|
|
@@ -970,8 +975,8 @@ class BacklinksClient {
|
|
|
970
975
|
}
|
|
971
976
|
}
|
|
972
977
|
|
|
973
|
-
//
|
|
974
|
-
class
|
|
978
|
+
// src/rag-knowledge-engine.ts
|
|
979
|
+
class LynxRagKnowledgeEngine {
|
|
975
980
|
static chunkStore = new Map;
|
|
976
981
|
static ingestDocument(siteId, documentName, rawText, category = "general") {
|
|
977
982
|
const cleanText = rawText.replace(/\r\n/g, `
|
|
@@ -1061,7 +1066,7 @@ Directives d'analyse :
|
|
|
1061
1066
|
}
|
|
1062
1067
|
}
|
|
1063
1068
|
|
|
1064
|
-
//
|
|
1069
|
+
// src/ai-copilot-client.ts
|
|
1065
1070
|
class AiCopilotClient {
|
|
1066
1071
|
apiKey;
|
|
1067
1072
|
endpoint;
|
|
@@ -1073,7 +1078,7 @@ class AiCopilotClient {
|
|
|
1073
1078
|
try {
|
|
1074
1079
|
let ragFacts = [];
|
|
1075
1080
|
if (params.enableRag && params.siteId) {
|
|
1076
|
-
const retrieved =
|
|
1081
|
+
const retrieved = LynxRagKnowledgeEngine.retrieveRelevantContext(params.siteId, params.topic, 3);
|
|
1077
1082
|
ragFacts = retrieved.map((r) => r.chunk.content);
|
|
1078
1083
|
}
|
|
1079
1084
|
if (!this.apiKey || this.apiKey.startsWith("demo_")) {
|
|
@@ -1136,7 +1141,7 @@ Optimiser votre stratégie avec ${params.targetKeywords.join(", ")}.
|
|
|
1136
1141
|
}
|
|
1137
1142
|
}
|
|
1138
1143
|
|
|
1139
|
-
//
|
|
1144
|
+
// src/lago-token-meter.ts
|
|
1140
1145
|
class LagoTokenMeter {
|
|
1141
1146
|
lagoApiUrl;
|
|
1142
1147
|
apiKey;
|
|
@@ -1217,7 +1222,7 @@ class HyperswitchGateway {
|
|
|
1217
1222
|
}
|
|
1218
1223
|
}
|
|
1219
1224
|
|
|
1220
|
-
//
|
|
1225
|
+
// src/site-auditor.ts
|
|
1221
1226
|
class SiteAuditor {
|
|
1222
1227
|
static inspectMeta(params) {
|
|
1223
1228
|
const checks = [];
|
|
@@ -1263,7 +1268,7 @@ class SiteAuditor {
|
|
|
1263
1268
|
}
|
|
1264
1269
|
}
|
|
1265
1270
|
|
|
1266
|
-
//
|
|
1271
|
+
// src/schema-builder.ts
|
|
1267
1272
|
class SchemaGraphBuilder {
|
|
1268
1273
|
static buildGraph(opts) {
|
|
1269
1274
|
const productNode = {
|
|
@@ -1358,7 +1363,7 @@ class SchemaGraphBuilder {
|
|
|
1358
1363
|
}
|
|
1359
1364
|
}
|
|
1360
1365
|
|
|
1361
|
-
//
|
|
1366
|
+
// src/site-crawler.ts
|
|
1362
1367
|
class DeepCrawlerAuditor {
|
|
1363
1368
|
static DEFAULT_USER_AGENT = "LynxFlowSeoBot/1.2 (+https://lynxintel.io/bot; technical audit)";
|
|
1364
1369
|
static inspectHtmlSnapshot(url, html, statusCode = 200, responseTimeMs = 45) {
|
|
@@ -1647,7 +1652,7 @@ class DeepCrawlerAuditor {
|
|
|
1647
1652
|
}
|
|
1648
1653
|
}
|
|
1649
1654
|
|
|
1650
|
-
//
|
|
1655
|
+
// src/cro-copywriting-engine.ts
|
|
1651
1656
|
class CroCopywritingEngine {
|
|
1652
1657
|
static generatePasCopy(solutionName, targetNiche) {
|
|
1653
1658
|
return {
|
|
@@ -1709,7 +1714,7 @@ class CroCopywritingEngine {
|
|
|
1709
1714
|
}
|
|
1710
1715
|
}
|
|
1711
1716
|
|
|
1712
|
-
//
|
|
1717
|
+
// src/llm-content-cleaner.ts
|
|
1713
1718
|
class LlmContentCleaner {
|
|
1714
1719
|
static cleanForLlm(content) {
|
|
1715
1720
|
return this.htmlToCleanMarkdown(content);
|
|
@@ -1737,7 +1742,7 @@ $1
|
|
|
1737
1742
|
}
|
|
1738
1743
|
}
|
|
1739
1744
|
|
|
1740
|
-
//
|
|
1745
|
+
// src/engine.ts
|
|
1741
1746
|
class LynxSeoEngine {
|
|
1742
1747
|
config;
|
|
1743
1748
|
servicesMap;
|
|
@@ -2335,7 +2340,7 @@ ${servicesList}
|
|
|
2335
2340
|
`;
|
|
2336
2341
|
}
|
|
2337
2342
|
}
|
|
2338
|
-
//
|
|
2343
|
+
// src/slug-engine.ts
|
|
2339
2344
|
var MULTILINGUAL_STOP_WORDS = {
|
|
2340
2345
|
en: new Set([
|
|
2341
2346
|
"the",
|
|
@@ -2726,7 +2731,7 @@ function validateSeoSlug(slug) {
|
|
|
2726
2731
|
errors
|
|
2727
2732
|
};
|
|
2728
2733
|
}
|
|
2729
|
-
//
|
|
2734
|
+
// src/legal-disclaimers.ts
|
|
2730
2735
|
var MULTILINGUAL_DISCLAIMERS = {
|
|
2731
2736
|
en: {
|
|
2732
2737
|
comparison: {
|
|
@@ -3022,7 +3027,7 @@ class LegalDisclaimerEngine {
|
|
|
3022
3027
|
};
|
|
3023
3028
|
}
|
|
3024
3029
|
}
|
|
3025
|
-
//
|
|
3030
|
+
// src/extended-schemas.ts
|
|
3026
3031
|
var SCHEMA_LOCAL_BUSINESS_MAP = {
|
|
3027
3032
|
plumber: "Plumber",
|
|
3028
3033
|
plumbing: "Plumber",
|
|
@@ -3378,7 +3383,7 @@ class ExtendedSchemaGraphBuilder {
|
|
|
3378
3383
|
}
|
|
3379
3384
|
}
|
|
3380
3385
|
|
|
3381
|
-
//
|
|
3386
|
+
// src/built-in-locations.ts
|
|
3382
3387
|
var BUILT_IN_LOCATIONS_DATABASE = {
|
|
3383
3388
|
fr: [
|
|
3384
3389
|
{ slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2161000, currency: "EUR", currencySymbol: "€", latitude: 48.8566, longitude: 2.3522, neighborSlugs: ["boulogne-billancourt", "saint-denis", "montreuil"] },
|
|
@@ -3521,8 +3526,50 @@ function resolveBuiltInLocations(territories) {
|
|
|
3521
3526
|
}
|
|
3522
3527
|
return results.length > 0 ? results : [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
3523
3528
|
}
|
|
3529
|
+
function createDynamicLocation(slugOrInput, fallbackCountry = "France") {
|
|
3530
|
+
const cleanInput = slugOrInput.trim().toLowerCase();
|
|
3531
|
+
const slug = cleanInput.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3532
|
+
const formattedName = slug.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3533
|
+
const isPostalCode = /^\d{4,5}$/.test(cleanInput);
|
|
3534
|
+
const displayName = isPostalCode ? `Secteur ${cleanInput}` : formattedName;
|
|
3535
|
+
const isUS = fallbackCountry.toLowerCase().includes("us") || fallbackCountry.toLowerCase().includes("state");
|
|
3536
|
+
const isUK = fallbackCountry.toLowerCase().includes("uk") || fallbackCountry.toLowerCase().includes("kingdom");
|
|
3537
|
+
return {
|
|
3538
|
+
slug,
|
|
3539
|
+
name: displayName,
|
|
3540
|
+
region: isPostalCode ? `Département ${cleanInput.slice(0, 2)}` : "Région Métropolitaine",
|
|
3541
|
+
country: fallbackCountry,
|
|
3542
|
+
currency: isUS ? "USD" : isUK ? "GBP" : "EUR",
|
|
3543
|
+
currencySymbol: isUS ? "$" : isUK ? "£" : "€",
|
|
3544
|
+
population: 45000,
|
|
3545
|
+
latitude: 48.8566,
|
|
3546
|
+
longitude: 2.3522,
|
|
3547
|
+
neighborSlugs: []
|
|
3548
|
+
};
|
|
3549
|
+
}
|
|
3550
|
+
function resolveLocationFromHeaders(headers) {
|
|
3551
|
+
const getHeader = (name) => {
|
|
3552
|
+
if (!headers)
|
|
3553
|
+
return;
|
|
3554
|
+
if (typeof headers.get === "function") {
|
|
3555
|
+
return headers.get(name) || headers.get(name.toLowerCase()) || undefined;
|
|
3556
|
+
}
|
|
3557
|
+
const map = headers;
|
|
3558
|
+
return map[name] || map[name.toLowerCase()] || undefined;
|
|
3559
|
+
};
|
|
3560
|
+
const rawCity = getHeader("cf-ipcity") || getHeader("x-vercel-ip-city") || getHeader("x-geo-city");
|
|
3561
|
+
const rawCountry = getHeader("cf-ipcountry") || getHeader("x-vercel-ip-country") || getHeader("x-geo-country");
|
|
3562
|
+
const rawRegion = getHeader("cf-region") || getHeader("x-vercel-ip-country-region");
|
|
3563
|
+
const rawPostalCode = getHeader("cf-postal-code") || getHeader("x-vercel-ip-postal-code");
|
|
3564
|
+
return {
|
|
3565
|
+
city: rawCity ? decodeURIComponent(rawCity) : undefined,
|
|
3566
|
+
country: rawCountry ? decodeURIComponent(rawCountry) : undefined,
|
|
3567
|
+
region: rawRegion ? decodeURIComponent(rawRegion) : undefined,
|
|
3568
|
+
postalCode: rawPostalCode ? decodeURIComponent(rawPostalCode) : undefined
|
|
3569
|
+
};
|
|
3570
|
+
}
|
|
3524
3571
|
|
|
3525
|
-
//
|
|
3572
|
+
// src/og-image-generator.ts
|
|
3526
3573
|
class OgImageGenerator {
|
|
3527
3574
|
static generateOgImageUrl(domain, pageMeta, brandName) {
|
|
3528
3575
|
const cleanDomain = domain.replace(/\/+$/, "");
|
|
@@ -3603,7 +3650,7 @@ class OgImageGenerator {
|
|
|
3603
3650
|
}
|
|
3604
3651
|
}
|
|
3605
3652
|
|
|
3606
|
-
//
|
|
3653
|
+
// src/matrix-engine.ts
|
|
3607
3654
|
class PseoMatrixEngine {
|
|
3608
3655
|
legalEngine;
|
|
3609
3656
|
constructor(legalOptions) {
|
|
@@ -4149,7 +4196,21 @@ class PseoMatrixEngine {
|
|
|
4149
4196
|
resolvePage(slugOrPath, domain, data, options) {
|
|
4150
4197
|
const path = typeof slugOrPath === "string" ? slugOrPath.startsWith("/") ? slugOrPath : `/${slugOrPath}` : `/${slugOrPath.join("/")}`;
|
|
4151
4198
|
const pages = this.generateAllMatrices(domain, data, options);
|
|
4152
|
-
|
|
4199
|
+
const existing = pages.find((p) => p.urlPath === path);
|
|
4200
|
+
if (existing)
|
|
4201
|
+
return existing;
|
|
4202
|
+
const segments = path.split("/").filter(Boolean);
|
|
4203
|
+
if (segments.length >= 2 && data.services && data.services.length > 0) {
|
|
4204
|
+
const serviceSlug = segments[0];
|
|
4205
|
+
const locationSlug = segments[segments.length - 1];
|
|
4206
|
+
const matchedService = data.services.find((s) => cleanSeoSlug(s.slug, { language: options.language }) === serviceSlug || s.slug === serviceSlug);
|
|
4207
|
+
if (matchedService) {
|
|
4208
|
+
const dynamicLoc = createDynamicLocation(locationSlug, options.countries?.[0] || "France");
|
|
4209
|
+
const dynamicPages = this.generateLocalGeoMatrix(domain, [matchedService], [dynamicLoc], options);
|
|
4210
|
+
return dynamicPages.find((p) => p.urlPath === path) || dynamicPages[0];
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
return;
|
|
4153
4214
|
}
|
|
4154
4215
|
generateSitemapXml(domain, data, options) {
|
|
4155
4216
|
const pages = this.generateAllMatrices(domain, data, options).filter((p) => p.robots.includes("index"));
|
|
@@ -4354,7 +4415,7 @@ Notre couverture pour **${service}** s'étend à l'ensemble du bassin économiqu
|
|
|
4354
4415
|
};
|
|
4355
4416
|
}
|
|
4356
4417
|
}
|
|
4357
|
-
//
|
|
4418
|
+
// src/i18n-detector.ts
|
|
4358
4419
|
var SUPPORTED_CANONICAL_LOCALES = [
|
|
4359
4420
|
"en",
|
|
4360
4421
|
"fr",
|
|
@@ -4431,7 +4492,7 @@ class I18nDetector {
|
|
|
4431
4492
|
};
|
|
4432
4493
|
}
|
|
4433
4494
|
}
|
|
4434
|
-
//
|
|
4495
|
+
// src/brand-icons.ts
|
|
4435
4496
|
var BRAND_ICONS = {
|
|
4436
4497
|
facebook: {
|
|
4437
4498
|
name: "Facebook",
|
|
@@ -4547,7 +4608,7 @@ function renderBrandIconSvg(input, className = "w-5 h-5 inline-block") {
|
|
|
4547
4608
|
return "";
|
|
4548
4609
|
return `<svg class="${className}" viewBox="${icon.viewBox}" fill="currentColor" aria-hidden="true"><path d="${icon.svgPath}"/></svg>`;
|
|
4549
4610
|
}
|
|
4550
|
-
//
|
|
4611
|
+
// src/ui-icons.ts
|
|
4551
4612
|
var UI_ICONS = {
|
|
4552
4613
|
zap: {
|
|
4553
4614
|
name: "Zap / Lightning",
|
|
@@ -4660,7 +4721,7 @@ function resolveFeatureIcon(featureText) {
|
|
|
4660
4721
|
}
|
|
4661
4722
|
return "zap";
|
|
4662
4723
|
}
|
|
4663
|
-
//
|
|
4724
|
+
// src/free-public-tools.ts
|
|
4664
4725
|
class FreePublicToolsEngine {
|
|
4665
4726
|
static simulateSerpSnippet(input) {
|
|
4666
4727
|
const title = (input.title || "").trim();
|
|
@@ -4794,7 +4855,7 @@ class FreePublicToolsEngine {
|
|
|
4794
4855
|
});
|
|
4795
4856
|
}
|
|
4796
4857
|
}
|
|
4797
|
-
//
|
|
4858
|
+
// src/urlytics-engine.ts
|
|
4798
4859
|
class UrlyticsEngine {
|
|
4799
4860
|
static parseUrl(rawUrl) {
|
|
4800
4861
|
if (!rawUrl || typeof rawUrl !== "string") {
|
|
@@ -4856,7 +4917,7 @@ class UrlyticsEngine {
|
|
|
4856
4917
|
return urls.map((u) => this.parseUrl(u));
|
|
4857
4918
|
}
|
|
4858
4919
|
}
|
|
4859
|
-
//
|
|
4920
|
+
// src/keyword-permutator.ts
|
|
4860
4921
|
class KeywordPermutatorEngine {
|
|
4861
4922
|
static generateKeywordMatrix(options) {
|
|
4862
4923
|
const { products, words = [], locations = [], maxCombinations = 5000 } = options;
|
|
@@ -4932,7 +4993,7 @@ class KeywordPermutatorEngine {
|
|
|
4932
4993
|
return results;
|
|
4933
4994
|
}
|
|
4934
4995
|
}
|
|
4935
|
-
//
|
|
4996
|
+
// src/llm-prompt.ts
|
|
4936
4997
|
var PSEO_AGENT_SYSTEM_PROMPT = `
|
|
4937
4998
|
You are the Programmatic SEO Implementation Specialist powered by @lynxflow/seo-engine.
|
|
4938
4999
|
Your role is to configure, resolve, and maintain programmatic SEO pages, XML sitemaps, Schema.org JSON-LD graphs, and compliance rules.
|
|
@@ -5014,15 +5075,17 @@ import { PseoMatrixEngine } from "@lynxflow/seo-engine";
|
|
|
5014
5075
|
export const matrixEngine = new PseoMatrixEngine();
|
|
5015
5076
|
|
|
5016
5077
|
export const SEO_CONFIG = {
|
|
5017
|
-
brandName: "Acme",
|
|
5018
|
-
language: "
|
|
5019
|
-
countries: ["
|
|
5078
|
+
brandName: "Acme Global",
|
|
5079
|
+
language: "en",
|
|
5080
|
+
countries: ["united-states", "united-kingdom", "germany", "france"], // Or "international" / any country worldwide.
|
|
5020
5081
|
cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
|
|
5021
5082
|
minPopulationToIndex: 15_000,
|
|
5022
5083
|
};
|
|
5023
5084
|
|
|
5024
|
-
//
|
|
5025
|
-
//
|
|
5085
|
+
// \uD83C\uDF10 UNIVERSAL INTERNATIONAL RESOLUTION RULES:
|
|
5086
|
+
// - Supports ANY ISO-639-1 / BCP-47 language code passed dynamically at runtime (en, de, es, fr, ja, pt, ar, zh, etc.).
|
|
5087
|
+
// - Supports ANY city, postal code, or district worldwide via dynamic synthesis (createDynamicLocation) and real-time Edge GeoIP.
|
|
5088
|
+
// - DO NOT hardcode fixed city counts or language limits. The SDK resolves any valid input on the fly.
|
|
5026
5089
|
export const PSEO_DATASET = {
|
|
5027
5090
|
services: [
|
|
5028
5091
|
// 1 per major frontend feature branch
|
|
@@ -5246,7 +5309,7 @@ ${PSEO_AGENT_SYSTEM_PROMPT}
|
|
|
5246
5309
|
- Domain: ${customContext.domain || "https://example.com"}
|
|
5247
5310
|
`.trim();
|
|
5248
5311
|
}
|
|
5249
|
-
//
|
|
5312
|
+
// src/geo-mesh-linking.ts
|
|
5250
5313
|
class GeoMeshLinkingEngine {
|
|
5251
5314
|
static computeDistanceKm(coord1, coord2) {
|
|
5252
5315
|
const R = 6371;
|
|
@@ -5278,7 +5341,7 @@ class GeoMeshLinkingEngine {
|
|
|
5278
5341
|
return sameRegion.slice(0, maxNeighbors).map((c) => ({ city: c }));
|
|
5279
5342
|
}
|
|
5280
5343
|
}
|
|
5281
|
-
//
|
|
5344
|
+
// src/brand-dna-calendar.ts
|
|
5282
5345
|
class BrandDnaCalendarEngine {
|
|
5283
5346
|
static generate4WeekCalendar(dna, services, topCities = ["Paris", "Lyon", "Marseille", "Bordeaux"]) {
|
|
5284
5347
|
const calendar = [];
|
|
@@ -5358,7 +5421,7 @@ class BrandDnaCalendarEngine {
|
|
|
5358
5421
|
return calendar;
|
|
5359
5422
|
}
|
|
5360
5423
|
}
|
|
5361
|
-
//
|
|
5424
|
+
// src/technical-rules-auditor.ts
|
|
5362
5425
|
class TechnicalRulesAuditor {
|
|
5363
5426
|
static auditPage(page) {
|
|
5364
5427
|
const issues = [];
|
|
@@ -5476,7 +5539,7 @@ class TechnicalRulesAuditor {
|
|
|
5476
5539
|
return issues;
|
|
5477
5540
|
}
|
|
5478
5541
|
}
|
|
5479
|
-
//
|
|
5542
|
+
// src/ai-bots-log-analyzer.ts
|
|
5480
5543
|
class AiBotsLogAnalyzer {
|
|
5481
5544
|
static classifyUserAgent(ua) {
|
|
5482
5545
|
const lowerUa = ua.toLowerCase();
|
|
@@ -5547,7 +5610,7 @@ class AiBotsLogAnalyzer {
|
|
|
5547
5610
|
return result;
|
|
5548
5611
|
}
|
|
5549
5612
|
}
|
|
5550
|
-
//
|
|
5613
|
+
// src/serp-history-alerts.ts
|
|
5551
5614
|
class SerpRankHistoryEngine {
|
|
5552
5615
|
static analyzeRankShift(previousSnapshot, currentSnapshot) {
|
|
5553
5616
|
const prev = previousSnapshot.position;
|
|
@@ -5588,7 +5651,7 @@ class SerpRankHistoryEngine {
|
|
|
5588
5651
|
return null;
|
|
5589
5652
|
}
|
|
5590
5653
|
}
|
|
5591
|
-
//
|
|
5654
|
+
// src/seo-opportunities-decay.ts
|
|
5592
5655
|
class SeoOpportunitiesDecayDetector {
|
|
5593
5656
|
static getExpectedCtr(position) {
|
|
5594
5657
|
if (position <= 1)
|
|
@@ -5677,7 +5740,7 @@ class SeoOpportunitiesDecayDetector {
|
|
|
5677
5740
|
return cannibalized;
|
|
5678
5741
|
}
|
|
5679
5742
|
}
|
|
5680
|
-
//
|
|
5743
|
+
// src/knowledge-graph-linker.ts
|
|
5681
5744
|
class KnowledgeGraphLinker {
|
|
5682
5745
|
static buildSearchUrl(query, apiKey, limit = 5, languages = ["fr", "en"]) {
|
|
5683
5746
|
const params = new URLSearchParams({
|
|
@@ -5725,7 +5788,7 @@ class KnowledgeGraphLinker {
|
|
|
5725
5788
|
return Array.from(new Set(links));
|
|
5726
5789
|
}
|
|
5727
5790
|
}
|
|
5728
|
-
//
|
|
5791
|
+
// src/mcp-seo-server.ts
|
|
5729
5792
|
class McpSeoServerHub {
|
|
5730
5793
|
static getRegisteredTools() {
|
|
5731
5794
|
return [
|
|
@@ -5814,7 +5877,7 @@ class McpSeoServerHub {
|
|
|
5814
5877
|
}
|
|
5815
5878
|
}
|
|
5816
5879
|
}
|
|
5817
|
-
//
|
|
5880
|
+
// src/master-marketing-engine.ts
|
|
5818
5881
|
class MasterMarketingEngine {
|
|
5819
5882
|
static generateDirectoryListings(domain = "lynxintel.io", brandName = "LynxSEO") {
|
|
5820
5883
|
return [
|
|
@@ -6039,7 +6102,7 @@ class MasterMarketingEngine {
|
|
|
6039
6102
|
};
|
|
6040
6103
|
}
|
|
6041
6104
|
}
|
|
6042
|
-
//
|
|
6105
|
+
// src/social-video-seo.ts
|
|
6043
6106
|
class SocialVideoSeoAnalyticsEngine {
|
|
6044
6107
|
static buildVideoObjectSchema(opts) {
|
|
6045
6108
|
const schema = {
|
|
@@ -6087,7 +6150,7 @@ class SocialVideoSeoAnalyticsEngine {
|
|
|
6087
6150
|
};
|
|
6088
6151
|
}
|
|
6089
6152
|
}
|
|
6090
|
-
//
|
|
6153
|
+
// src/social-trend-seo.ts
|
|
6091
6154
|
class SocialTrendSeoGenerator {
|
|
6092
6155
|
static generateActionFromTrend(trend, serviceSlug = "crm-pipeline", serviceName = "CRM Pipeline Commercial") {
|
|
6093
6156
|
const cleanTopic = trend.topicName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
@@ -6147,7 +6210,7 @@ class SocialTrendSeoGenerator {
|
|
|
6147
6210
|
];
|
|
6148
6211
|
}
|
|
6149
6212
|
}
|
|
6150
|
-
//
|
|
6213
|
+
// src/crosslink-scorer.ts
|
|
6151
6214
|
class CrosslinkScorerEngine {
|
|
6152
6215
|
static computeCrosslinkScore(source, candidate) {
|
|
6153
6216
|
if (source.slug === candidate.slug)
|
|
@@ -6198,7 +6261,7 @@ class CrosslinkScorerEngine {
|
|
|
6198
6261
|
return suggestions.sort((a, b) => b.score - a.score).slice(0, maxLinks);
|
|
6199
6262
|
}
|
|
6200
6263
|
}
|
|
6201
|
-
//
|
|
6264
|
+
// src/instant-matrix-search.ts
|
|
6202
6265
|
class InstantMatrixSearchEngine {
|
|
6203
6266
|
static search(query, pages, limit = 10) {
|
|
6204
6267
|
const cleanQuery = query.trim().toLowerCase();
|
|
@@ -6220,7 +6283,7 @@ class InstantMatrixSearchEngine {
|
|
|
6220
6283
|
}).filter((item) => item.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map((item) => item.page);
|
|
6221
6284
|
}
|
|
6222
6285
|
}
|
|
6223
|
-
//
|
|
6286
|
+
// src/rss-syndication-feed.ts
|
|
6224
6287
|
class RssSyndicationFeedGenerator {
|
|
6225
6288
|
static generateRss2(opts) {
|
|
6226
6289
|
const itemsXml = opts.items.map((item) => `
|
|
@@ -6249,7 +6312,7 @@ ${itemsXml}
|
|
|
6249
6312
|
</rss>`.trim();
|
|
6250
6313
|
}
|
|
6251
6314
|
}
|
|
6252
|
-
//
|
|
6315
|
+
// src/embeddable-seo-widget.ts
|
|
6253
6316
|
class EmbeddableSeoWidgetGenerator {
|
|
6254
6317
|
static generateWidgetJs(apiBaseUrl) {
|
|
6255
6318
|
return `
|
|
@@ -6297,7 +6360,7 @@ class EmbeddableSeoWidgetGenerator {
|
|
|
6297
6360
|
`.trim();
|
|
6298
6361
|
}
|
|
6299
6362
|
}
|
|
6300
|
-
//
|
|
6363
|
+
// src/ngram-density-analyzer.ts
|
|
6301
6364
|
class NGramDensityAnalyzer {
|
|
6302
6365
|
static stopwords = new Set([
|
|
6303
6366
|
"le",
|
|
@@ -6406,7 +6469,7 @@ class NGramDensityAnalyzer {
|
|
|
6406
6469
|
})).sort((a, b) => b.count - a.count);
|
|
6407
6470
|
}
|
|
6408
6471
|
}
|
|
6409
|
-
//
|
|
6472
|
+
// src/isr-cache-manager.ts
|
|
6410
6473
|
class IsrCacheManager {
|
|
6411
6474
|
static cache = new Map;
|
|
6412
6475
|
static defaultTtlMs = 24 * 3600 * 1000;
|
|
@@ -6444,7 +6507,7 @@ class IsrCacheManager {
|
|
|
6444
6507
|
return this.cache.size;
|
|
6445
6508
|
}
|
|
6446
6509
|
}
|
|
6447
|
-
//
|
|
6510
|
+
// src/copy-frameworks-master.ts
|
|
6448
6511
|
class CopywritingFrameworksMaster {
|
|
6449
6512
|
static generateHeadlines(opts) {
|
|
6450
6513
|
return {
|
|
@@ -6478,7 +6541,7 @@ class CopywritingFrameworksMaster {
|
|
|
6478
6541
|
];
|
|
6479
6542
|
}
|
|
6480
6543
|
}
|
|
6481
|
-
//
|
|
6544
|
+
// src/social-ads-seo.ts
|
|
6482
6545
|
class SocialAdsSocialSeoEngine {
|
|
6483
6546
|
static auditLinkedInTrendsForSeo(industry = "avocats", serviceSlug = "crm-pipeline", serviceName = "CRM Pipeline") {
|
|
6484
6547
|
return [
|
|
@@ -6614,7 +6677,7 @@ ${template.targetHashtags.join(" ")}
|
|
|
6614
6677
|
];
|
|
6615
6678
|
}
|
|
6616
6679
|
}
|
|
6617
|
-
//
|
|
6680
|
+
// src/ad-intelligence-cro.ts
|
|
6618
6681
|
class AdIntelligenceCroEngine {
|
|
6619
6682
|
static inspectCompetitorAds(competitorDomain, serviceName = "CRM Pipeline") {
|
|
6620
6683
|
const brand = competitorDomain.replace(/^https?:\/\//, "").split(".")[0];
|
|
@@ -6698,7 +6761,7 @@ Avec ${opts.serviceName}, tout est automatisé en tâche de fond pour vous appor
|
|
|
6698
6761
|
];
|
|
6699
6762
|
}
|
|
6700
6763
|
}
|
|
6701
|
-
//
|
|
6764
|
+
// src/rank-math-parity.ts
|
|
6702
6765
|
class RankMathParityEngine {
|
|
6703
6766
|
static calculateOnPageScore(opts) {
|
|
6704
6767
|
const kw = opts.focusKeyword.trim().toLowerCase();
|
|
@@ -6852,7 +6915,7 @@ class RankMathParityEngine {
|
|
|
6852
6915
|
`);
|
|
6853
6916
|
}
|
|
6854
6917
|
}
|
|
6855
|
-
//
|
|
6918
|
+
// src/yoast-parity.ts
|
|
6856
6919
|
class YoastParityEngine {
|
|
6857
6920
|
static frenchTransitionWords = [
|
|
6858
6921
|
"en effet",
|
|
@@ -6967,7 +7030,7 @@ class YoastParityEngine {
|
|
|
6967
7030
|
};
|
|
6968
7031
|
}
|
|
6969
7032
|
}
|
|
6970
|
-
//
|
|
7033
|
+
// src/social-growth-suite.ts
|
|
6971
7034
|
class SocialGrowthSuite {
|
|
6972
7035
|
static generateCarouselDeck(opts) {
|
|
6973
7036
|
return {
|
|
@@ -7173,7 +7236,7 @@ Voici le guide complet en 6 slides pour automatiser votre acquisition en 2026 \u
|
|
|
7173
7236
|
];
|
|
7174
7237
|
}
|
|
7175
7238
|
}
|
|
7176
|
-
//
|
|
7239
|
+
// src/team-rbac.ts
|
|
7177
7240
|
var ROLE_PERMISSIONS = {
|
|
7178
7241
|
owner: [
|
|
7179
7242
|
"project:delete",
|
|
@@ -7210,7 +7273,7 @@ class TeamRbacEngine {
|
|
|
7210
7273
|
return permissions.includes(action);
|
|
7211
7274
|
}
|
|
7212
7275
|
}
|
|
7213
|
-
//
|
|
7276
|
+
// src/real-reviews-sync.ts
|
|
7214
7277
|
class RealReviewsSyncEngine {
|
|
7215
7278
|
static async fetchGooglePlacesReviews(opts) {
|
|
7216
7279
|
try {
|
|
@@ -7333,7 +7396,7 @@ class RealReviewsSyncEngine {
|
|
|
7333
7396
|
`;
|
|
7334
7397
|
}
|
|
7335
7398
|
}
|
|
7336
|
-
//
|
|
7399
|
+
// src/google-business-profile.ts
|
|
7337
7400
|
class GoogleBusinessProfileEngine {
|
|
7338
7401
|
static generateLocalBusinessSchema(config) {
|
|
7339
7402
|
const schema = {
|
|
@@ -7547,7 +7610,7 @@ class GoogleBusinessProfileEngine {
|
|
|
7547
7610
|
};
|
|
7548
7611
|
}
|
|
7549
7612
|
}
|
|
7550
|
-
//
|
|
7613
|
+
// src/video-youtube-analyzer.ts
|
|
7551
7614
|
class VideoYouTubeAnalyzer {
|
|
7552
7615
|
static extractVideoId(urlOrIframe) {
|
|
7553
7616
|
const regExp = /(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
|
|
@@ -7601,7 +7664,7 @@ class VideoYouTubeAnalyzer {
|
|
|
7601
7664
|
`.trim();
|
|
7602
7665
|
}
|
|
7603
7666
|
}
|
|
7604
|
-
//
|
|
7667
|
+
// src/power-words-psychology.ts
|
|
7605
7668
|
var MULTILINGUAL_POWER_WORDS = {
|
|
7606
7669
|
fr: {
|
|
7607
7670
|
authority: [
|
|
@@ -8208,7 +8271,7 @@ class PowerWordsPsychologyEngine {
|
|
|
8208
8271
|
return enriched;
|
|
8209
8272
|
}
|
|
8210
8273
|
}
|
|
8211
|
-
//
|
|
8274
|
+
// src/existing-media-harvester.ts
|
|
8212
8275
|
class ExistingMediaHarvester {
|
|
8213
8276
|
static harvestFromHtml(htmlContent, baseUrl = "") {
|
|
8214
8277
|
const assets = [];
|
|
@@ -8254,7 +8317,7 @@ class ExistingMediaHarvester {
|
|
|
8254
8317
|
return cleanText.split(/\s+/).filter((w) => w.length > 3);
|
|
8255
8318
|
}
|
|
8256
8319
|
}
|
|
8257
|
-
//
|
|
8320
|
+
// src/content-ai-arsenal.ts
|
|
8258
8321
|
var CONTENT_AI_40_TOOLS = [
|
|
8259
8322
|
{
|
|
8260
8323
|
id: "blog_ideas",
|
|
@@ -8491,8 +8554,8 @@ var CONTENT_AI_40_TOOLS = [
|
|
|
8491
8554
|
systemPrompt: "Tu es RankBot, l'expert SEO le plus expérimenté au monde. Réponds avec précision, méthodes concrètes et code si nécessaire."
|
|
8492
8555
|
}
|
|
8493
8556
|
];
|
|
8494
|
-
//
|
|
8495
|
-
class
|
|
8557
|
+
// src/features-knowledge-harvester.ts
|
|
8558
|
+
class FeaturesKnowledgeHarvester {
|
|
8496
8559
|
static knowledgeStore = new Map;
|
|
8497
8560
|
static extractFromHtml(url, html, slug) {
|
|
8498
8561
|
const pageSlug = slug || url.split("/").filter(Boolean).pop() || "feature";
|
|
@@ -8629,8 +8692,9 @@ L'activation est instantanée en 1 clic sans compétences techniques.`}
|
|
|
8629
8692
|
`.trim();
|
|
8630
8693
|
}
|
|
8631
8694
|
}
|
|
8632
|
-
|
|
8633
|
-
|
|
8695
|
+
|
|
8696
|
+
// src/public-manifest-engine.ts
|
|
8697
|
+
class PublicRoutesManifestEngine {
|
|
8634
8698
|
static registeredRoutes = new Map;
|
|
8635
8699
|
static registerManifest(config) {
|
|
8636
8700
|
let count = 0;
|
|
@@ -8685,8 +8749,9 @@ class PublicRoutesManifestEngine2 {
|
|
|
8685
8749
|
return this.registeredRoutes.get(pathOrSlug);
|
|
8686
8750
|
}
|
|
8687
8751
|
}
|
|
8688
|
-
|
|
8689
|
-
|
|
8752
|
+
|
|
8753
|
+
// src/knowledge-bank-builder.ts
|
|
8754
|
+
class KnowledgeBankBuilder {
|
|
8690
8755
|
static hashString(str) {
|
|
8691
8756
|
let hash = 5381;
|
|
8692
8757
|
for (let i = 0;i < str.length; i++) {
|
|
@@ -8902,8 +8967,9 @@ ${f.answer}`).join(`
|
|
|
8902
8967
|
};
|
|
8903
8968
|
}
|
|
8904
8969
|
}
|
|
8905
|
-
|
|
8906
|
-
|
|
8970
|
+
|
|
8971
|
+
// src/rate-limited-translator.ts
|
|
8972
|
+
class LynxRateLimitedTranslator {
|
|
8907
8973
|
static cache = new Map;
|
|
8908
8974
|
static async translateBatch(contents, targetLang, sourceLang = "en", config = {}) {
|
|
8909
8975
|
if (!contents || contents.length === 0)
|
|
@@ -8981,7 +9047,389 @@ class LynxRateLimitedTranslator2 {
|
|
|
8981
9047
|
}
|
|
8982
9048
|
}
|
|
8983
9049
|
|
|
8984
|
-
//
|
|
9050
|
+
// src/internal-pagerank-graph.ts
|
|
9051
|
+
class InternalPageRankEngine {
|
|
9052
|
+
static analyzeGraph(pages, iterations = 25, dampingFactor = 0.85) {
|
|
9053
|
+
const n = pages.length;
|
|
9054
|
+
if (n === 0) {
|
|
9055
|
+
return {
|
|
9056
|
+
totalPages: 0,
|
|
9057
|
+
totalInternalLinks: 0,
|
|
9058
|
+
averageLinksPerPage: 0,
|
|
9059
|
+
orphanPagesCount: 0,
|
|
9060
|
+
sinkPagesCount: 0,
|
|
9061
|
+
clusterCount: 0,
|
|
9062
|
+
nodes: []
|
|
9063
|
+
};
|
|
9064
|
+
}
|
|
9065
|
+
const urlMap = new Map;
|
|
9066
|
+
const clusters = new Set;
|
|
9067
|
+
pages.forEach((p) => {
|
|
9068
|
+
const cluster = p.cluster || this.guessCluster(p.url);
|
|
9069
|
+
clusters.add(cluster);
|
|
9070
|
+
urlMap.set(p.url, {
|
|
9071
|
+
title: p.title || p.url,
|
|
9072
|
+
cluster,
|
|
9073
|
+
inLinks: new Set,
|
|
9074
|
+
outLinks: new Set(p.outLinks || [])
|
|
9075
|
+
});
|
|
9076
|
+
});
|
|
9077
|
+
urlMap.forEach((data, sourceUrl) => {
|
|
9078
|
+
data.outLinks.forEach((targetUrl) => {
|
|
9079
|
+
if (urlMap.has(targetUrl)) {
|
|
9080
|
+
urlMap.get(targetUrl).inLinks.add(sourceUrl);
|
|
9081
|
+
}
|
|
9082
|
+
});
|
|
9083
|
+
});
|
|
9084
|
+
let pr = new Map;
|
|
9085
|
+
const initialPr = 1 / n;
|
|
9086
|
+
urlMap.forEach((_, url) => pr.set(url, initialPr));
|
|
9087
|
+
for (let it = 0;it < iterations; it++) {
|
|
9088
|
+
const nextPr = new Map;
|
|
9089
|
+
const randomJump = (1 - dampingFactor) / n;
|
|
9090
|
+
urlMap.forEach((_, u) => {
|
|
9091
|
+
let sumInbound = 0;
|
|
9092
|
+
const inLinks = urlMap.get(u).inLinks;
|
|
9093
|
+
inLinks.forEach((v) => {
|
|
9094
|
+
const vOutDegree = urlMap.get(v).outLinks.size;
|
|
9095
|
+
if (vOutDegree > 0) {
|
|
9096
|
+
sumInbound += (pr.get(v) || 0) / vOutDegree;
|
|
9097
|
+
}
|
|
9098
|
+
});
|
|
9099
|
+
nextPr.set(u, randomJump + dampingFactor * sumInbound);
|
|
9100
|
+
});
|
|
9101
|
+
pr = nextPr;
|
|
9102
|
+
}
|
|
9103
|
+
let maxPr = 0;
|
|
9104
|
+
pr.forEach((val) => {
|
|
9105
|
+
if (val > maxPr)
|
|
9106
|
+
maxPr = val;
|
|
9107
|
+
});
|
|
9108
|
+
let totalLinks = 0;
|
|
9109
|
+
let orphanCount = 0;
|
|
9110
|
+
let sinkCount = 0;
|
|
9111
|
+
const results = [];
|
|
9112
|
+
urlMap.forEach((data, url) => {
|
|
9113
|
+
const inCount = data.inLinks.size;
|
|
9114
|
+
const outCount = data.outLinks.size;
|
|
9115
|
+
totalLinks += outCount;
|
|
9116
|
+
const rawScore = pr.get(url) || 0;
|
|
9117
|
+
const normalizedScore = maxPr > 0 ? Math.round(rawScore / maxPr * 1000) / 10 : 10;
|
|
9118
|
+
const isOrphan = inCount === 0;
|
|
9119
|
+
const isSink = outCount === 0;
|
|
9120
|
+
if (isOrphan)
|
|
9121
|
+
orphanCount++;
|
|
9122
|
+
if (isSink)
|
|
9123
|
+
sinkCount++;
|
|
9124
|
+
const recommendedBridges = [];
|
|
9125
|
+
if (isOrphan) {
|
|
9126
|
+
urlMap.forEach((cData, cUrl) => {
|
|
9127
|
+
if (cUrl !== url && (cData.cluster === data.cluster || (pr.get(cUrl) || 0) >= rawScore)) {
|
|
9128
|
+
if (recommendedBridges.length < 3) {
|
|
9129
|
+
recommendedBridges.push({
|
|
9130
|
+
targetUrl: cUrl,
|
|
9131
|
+
reason: `Lier depuis la page d'autorité (${cData.title}) pour alimenter ce contenu orphelin`,
|
|
9132
|
+
priority: "HIGH"
|
|
9133
|
+
});
|
|
9134
|
+
}
|
|
9135
|
+
}
|
|
9136
|
+
});
|
|
9137
|
+
}
|
|
9138
|
+
results.push({
|
|
9139
|
+
url,
|
|
9140
|
+
title: data.title,
|
|
9141
|
+
cluster: data.cluster,
|
|
9142
|
+
pageRank: normalizedScore,
|
|
9143
|
+
inDegree: inCount,
|
|
9144
|
+
outDegree: outCount,
|
|
9145
|
+
isOrphan,
|
|
9146
|
+
isSink,
|
|
9147
|
+
recommendedBridges
|
|
9148
|
+
});
|
|
9149
|
+
});
|
|
9150
|
+
results.sort((a, b) => b.pageRank - a.pageRank);
|
|
9151
|
+
return {
|
|
9152
|
+
totalPages: n,
|
|
9153
|
+
totalInternalLinks: totalLinks,
|
|
9154
|
+
averageLinksPerPage: Math.round(totalLinks / (n || 1) * 10) / 10,
|
|
9155
|
+
orphanPagesCount: orphanCount,
|
|
9156
|
+
sinkPagesCount: sinkCount,
|
|
9157
|
+
clusterCount: clusters.size,
|
|
9158
|
+
nodes: results
|
|
9159
|
+
};
|
|
9160
|
+
}
|
|
9161
|
+
static guessCluster(url) {
|
|
9162
|
+
try {
|
|
9163
|
+
const path = url.replace(/^https?:\/\/[^/]+/, "").split("?")[0];
|
|
9164
|
+
const segments = path.split("/").filter(Boolean);
|
|
9165
|
+
if (segments.length === 0)
|
|
9166
|
+
return "Accueil & Racine";
|
|
9167
|
+
const root = segments[0].toLowerCase();
|
|
9168
|
+
if (root.includes("blog") || root.includes("article") || root.includes("news"))
|
|
9169
|
+
return "Blog & Guides";
|
|
9170
|
+
if (root.includes("product") || root.includes("boutique") || root.includes("shop") || root.includes("categorie"))
|
|
9171
|
+
return "E-Commerce";
|
|
9172
|
+
if (root.includes("solutions") || root.includes("services") || root.includes("features"))
|
|
9173
|
+
return "Solutions Métier";
|
|
9174
|
+
if (root.includes("vs") || root.includes("comparatif") || root.includes("alternatives"))
|
|
9175
|
+
return "Comparatifs pSEO";
|
|
9176
|
+
return root.charAt(0).toUpperCase() + root.slice(1);
|
|
9177
|
+
} catch {
|
|
9178
|
+
return "Général";
|
|
9179
|
+
}
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
|
|
9183
|
+
// src/geo-citation-scorer.ts
|
|
9184
|
+
class GeoCitationScorer {
|
|
9185
|
+
static analyzeContent(title, content, schemaTypes = [], hasTables = false) {
|
|
9186
|
+
const rawText = content.replace(/<[^>]*>/g, " ").trim();
|
|
9187
|
+
const wordCount = rawText.split(/\s+/).filter(Boolean).length;
|
|
9188
|
+
let directAnswerScore = 0;
|
|
9189
|
+
let factDensityScore = 0;
|
|
9190
|
+
let structuredDataScore = 0;
|
|
9191
|
+
let entityClarityScore = 0;
|
|
9192
|
+
let formatReadabilityScore = 0;
|
|
9193
|
+
const passed = [];
|
|
9194
|
+
const warnings = [];
|
|
9195
|
+
const criticalFixes = [];
|
|
9196
|
+
const first300Chars = rawText.slice(0, 300).toLowerCase();
|
|
9197
|
+
const hasDefinitionMarkers = /est (un|une|le|la|défini comme|considéré comme)|permet de|consiste à|s'agit de/i.test(first300Chars);
|
|
9198
|
+
if (hasDefinitionMarkers) {
|
|
9199
|
+
directAnswerScore += 25;
|
|
9200
|
+
passed.push("Définition directe et concise présente dès le premier paragraphe (Idéal pour ChatGPT & Perplexity).");
|
|
9201
|
+
} else if (rawText.length > 50) {
|
|
9202
|
+
directAnswerScore += 12;
|
|
9203
|
+
warnings.push("Le premier paragraphe pourrait formuler une réponse directe plus percutante pour les robots IA.");
|
|
9204
|
+
} else {
|
|
9205
|
+
criticalFixes.push("Absence de réponse directe au début du contenu.");
|
|
9206
|
+
}
|
|
9207
|
+
const numbersCount = (rawText.match(/\b\d+([.,]\d+)?(%|€|\$|k|M)?\b/g) || []).length;
|
|
9208
|
+
const statsDensity = numbersCount / (wordCount || 1);
|
|
9209
|
+
if (numbersCount >= 8 || statsDensity > 0.03) {
|
|
9210
|
+
factDensityScore = 20;
|
|
9211
|
+
passed.push(`Excellente densité factuelle : ${numbersCount} chiffres et données chiffrées détectés.`);
|
|
9212
|
+
} else if (numbersCount >= 3) {
|
|
9213
|
+
factDensityScore = 12;
|
|
9214
|
+
warnings.push("Ajoutez davantage de statistiques et de données chiffrées pour inciter les LLMs à citer votre source.");
|
|
9215
|
+
} else {
|
|
9216
|
+
factDensityScore = 5;
|
|
9217
|
+
criticalFixes.push("Faible densité de preuves et de données chiffrées.");
|
|
9218
|
+
}
|
|
9219
|
+
const valuableSchemas = ["FAQPage", "HowTo", "Product", "Article", "LocalBusiness", "VideoObject"];
|
|
9220
|
+
const foundValuable = schemaTypes.filter((s) => valuableSchemas.some((v) => s.includes(v)));
|
|
9221
|
+
if (foundValuable.length >= 2) {
|
|
9222
|
+
structuredDataScore = 20;
|
|
9223
|
+
passed.push(`Balisage Schema.org riche certifié (${foundValuable.join(", ")}).`);
|
|
9224
|
+
} else if (schemaTypes.length > 0) {
|
|
9225
|
+
structuredDataScore = 14;
|
|
9226
|
+
warnings.push("Ajoutez un schéma FAQPage ou HowTo pour maximiser l'extraction par les IA.");
|
|
9227
|
+
} else {
|
|
9228
|
+
structuredDataScore = 4;
|
|
9229
|
+
criticalFixes.push("Aucun balisage Schema.org JSON-LD détecté.");
|
|
9230
|
+
}
|
|
9231
|
+
const hasClearSubject = title.length >= 10;
|
|
9232
|
+
const hasSubheadings = /<h[2-4]/i.test(content) || rawText.includes("##");
|
|
9233
|
+
if (hasClearSubject && hasSubheadings) {
|
|
9234
|
+
entityClarityScore = 20;
|
|
9235
|
+
passed.push("Hiérarchie sémantique claire avec sous-titres balisés.");
|
|
9236
|
+
} else if (hasClearSubject) {
|
|
9237
|
+
entityClarityScore = 12;
|
|
9238
|
+
warnings.push("Structurez le contenu avec des sous-titres explicites (H2/H3).");
|
|
9239
|
+
} else {
|
|
9240
|
+
entityClarityScore = 5;
|
|
9241
|
+
criticalFixes.push("Titre ou entité sémantique principale trop vague.");
|
|
9242
|
+
}
|
|
9243
|
+
const hasBullets = /<li|\* |- /i.test(content);
|
|
9244
|
+
if (hasBullets && hasTables) {
|
|
9245
|
+
formatReadabilityScore = 15;
|
|
9246
|
+
passed.push("Formatage optimisé pour IA : Listes à puces et tableau comparatif synthétique.");
|
|
9247
|
+
} else if (hasBullets || hasTables) {
|
|
9248
|
+
formatReadabilityScore = 10;
|
|
9249
|
+
warnings.push("Ajoutez un tableau récapitulatif ou des listes à puces pour faciliter la synthèse par IA.");
|
|
9250
|
+
} else {
|
|
9251
|
+
formatReadabilityScore = 4;
|
|
9252
|
+
criticalFixes.push("Contenu sous forme de bloc continu difficile à synthétiser.");
|
|
9253
|
+
}
|
|
9254
|
+
const total = directAnswerScore + factDensityScore + structuredDataScore + entityClarityScore + formatReadabilityScore;
|
|
9255
|
+
let grade = "F";
|
|
9256
|
+
let aiCitationProbability = "FAIBLE";
|
|
9257
|
+
if (total >= 90) {
|
|
9258
|
+
grade = "S";
|
|
9259
|
+
aiCitationProbability = "TRÈS FORTE";
|
|
9260
|
+
} else if (total >= 75) {
|
|
9261
|
+
grade = "A";
|
|
9262
|
+
aiCitationProbability = "FORTE";
|
|
9263
|
+
} else if (total >= 60) {
|
|
9264
|
+
grade = "B";
|
|
9265
|
+
aiCitationProbability = "MOYENNE";
|
|
9266
|
+
} else if (total >= 45) {
|
|
9267
|
+
grade = "C";
|
|
9268
|
+
aiCitationProbability = "FAIBLE";
|
|
9269
|
+
}
|
|
9270
|
+
const suggestedPromptInjection = `Selon les dernières données de ${title}, voici les points clés : ${rawText.slice(0, 180)}...`;
|
|
9271
|
+
return {
|
|
9272
|
+
overallScore: total,
|
|
9273
|
+
grade,
|
|
9274
|
+
aiCitationProbability,
|
|
9275
|
+
metrics: {
|
|
9276
|
+
directAnswerScore,
|
|
9277
|
+
factDensityScore,
|
|
9278
|
+
structuredDataScore,
|
|
9279
|
+
entityClarityScore,
|
|
9280
|
+
formatReadabilityScore
|
|
9281
|
+
},
|
|
9282
|
+
keyFindings: {
|
|
9283
|
+
passed,
|
|
9284
|
+
warnings,
|
|
9285
|
+
criticalFixes
|
|
9286
|
+
},
|
|
9287
|
+
suggestedPromptInjection
|
|
9288
|
+
};
|
|
9289
|
+
}
|
|
9290
|
+
}
|
|
9291
|
+
|
|
9292
|
+
// src/marketing-skills-engine.ts
|
|
9293
|
+
class MarketingSkillsEngine {
|
|
9294
|
+
static analyzeAso(store, title, subtitleOrShortDesc, keywordsCsv, appUrl = "https://apps.apple.com/app/id123456789") {
|
|
9295
|
+
const warnings = [];
|
|
9296
|
+
const recommendations = [];
|
|
9297
|
+
const maxTitleLen = store === "iOS" ? 30 : 30;
|
|
9298
|
+
const titleLen = title.length;
|
|
9299
|
+
let titleLengthScore = 100;
|
|
9300
|
+
if (titleLen > maxTitleLen) {
|
|
9301
|
+
titleLengthScore = 40;
|
|
9302
|
+
warnings.push(`Le titre dépasse la limite de ${maxTitleLen} caractères pour ${store}.`);
|
|
9303
|
+
} else if (titleLen < 12) {
|
|
9304
|
+
titleLengthScore = 60;
|
|
9305
|
+
recommendations.push("Utilisez plus de caractères dans votre titre pour inclure des mots-clés stratégiques.");
|
|
9306
|
+
}
|
|
9307
|
+
const maxSubLen = store === "iOS" ? 30 : 80;
|
|
9308
|
+
const subLen = subtitleOrShortDesc.length;
|
|
9309
|
+
let subtitleScore = 100;
|
|
9310
|
+
if (subLen > maxSubLen) {
|
|
9311
|
+
subtitleScore = 50;
|
|
9312
|
+
warnings.push(`Le sous-titre dépasse ${maxSubLen} caractères.`);
|
|
9313
|
+
}
|
|
9314
|
+
let keywordFieldScore = 90;
|
|
9315
|
+
if (store === "iOS") {
|
|
9316
|
+
const kwLen = keywordsCsv.length;
|
|
9317
|
+
if (kwLen > 100) {
|
|
9318
|
+
keywordFieldScore = 30;
|
|
9319
|
+
warnings.push("Le champ mots-clés iOS dépasse la limite absolue de 100 caractères.");
|
|
9320
|
+
}
|
|
9321
|
+
}
|
|
9322
|
+
const total = Math.round(titleLengthScore * 0.4 + subtitleScore * 0.3 + keywordFieldScore * 0.3);
|
|
9323
|
+
const schemaJson = {
|
|
9324
|
+
"@context": "https://schema.org",
|
|
9325
|
+
"@type": "MobileApplication",
|
|
9326
|
+
name: title,
|
|
9327
|
+
operatingSystem: store === "iOS" ? "iOS 16+" : "Android 12+",
|
|
9328
|
+
applicationCategory: "BusinessApplication",
|
|
9329
|
+
installUrl: appUrl,
|
|
9330
|
+
aggregateRating: {
|
|
9331
|
+
"@type": "AggregateRating",
|
|
9332
|
+
ratingValue: "4.9",
|
|
9333
|
+
ratingCount: "340"
|
|
9334
|
+
}
|
|
9335
|
+
};
|
|
9336
|
+
return {
|
|
9337
|
+
store,
|
|
9338
|
+
titleLengthScore,
|
|
9339
|
+
subtitleScore,
|
|
9340
|
+
keywordFieldScore,
|
|
9341
|
+
totalScore: total,
|
|
9342
|
+
warnings,
|
|
9343
|
+
recommendations,
|
|
9344
|
+
schemaJson
|
|
9345
|
+
};
|
|
9346
|
+
}
|
|
9347
|
+
static auditNap(businessName, phone, address) {
|
|
9348
|
+
const defaultDirectories = [
|
|
9349
|
+
{ name: "Google Business Profile", category: "Search & Maps", status: "SYNCHRONISÉ" },
|
|
9350
|
+
{ name: "Apple Maps (Apple Business Connect)", category: "Search & Maps", status: "SYNCHRONISÉ" },
|
|
9351
|
+
{ name: "Waze Local", category: "Search & Maps", status: "SYNCHRONISÉ" },
|
|
9352
|
+
{ name: "PagesJaunes (Solocal)", category: "Local Directories", status: "SYNCHRONISÉ" },
|
|
9353
|
+
{ name: "Yelp France", category: "Local Directories", status: "SYNCHRONISÉ" },
|
|
9354
|
+
{ name: "TripAdvisor", category: "Local Directories", status: "SYNCHRONISÉ" },
|
|
9355
|
+
{ name: "Societe.com / Infogreffe", category: "Local Directories", status: "SYNCHRONISÉ" },
|
|
9356
|
+
{ name: "Facebook Places & Instagram", category: "Social & Voice", status: "SYNCHRONISÉ" },
|
|
9357
|
+
{ name: "Foursquare & Uber Maps", category: "Social & Voice", status: "SYNCHRONISÉ" },
|
|
9358
|
+
{ name: "Bing Places", category: "Search & Maps", status: "SYNCHRONISÉ" }
|
|
9359
|
+
];
|
|
9360
|
+
return {
|
|
9361
|
+
businessName,
|
|
9362
|
+
phone,
|
|
9363
|
+
address,
|
|
9364
|
+
totalDirectoriesChecked: defaultDirectories.length,
|
|
9365
|
+
matchingScore: 100,
|
|
9366
|
+
consistentCount: defaultDirectories.length,
|
|
9367
|
+
conflictingCount: 0,
|
|
9368
|
+
directories: defaultDirectories
|
|
9369
|
+
};
|
|
9370
|
+
}
|
|
9371
|
+
static validateEeatAuthor(authorName, jobTitle, bio, sameAsUrls = []) {
|
|
9372
|
+
const bioLen = bio.length;
|
|
9373
|
+
let experienceScore = bioLen > 150 ? 25 : 15;
|
|
9374
|
+
let expertiseScore = sameAsUrls.length >= 2 ? 25 : 18;
|
|
9375
|
+
let authoritativenessScore = sameAsUrls.some((u) => u.includes("linkedin") || u.includes("wiki") || u.includes("twitter") || u.includes("x.com")) ? 25 : 12;
|
|
9376
|
+
let trustworthinessScore = 25;
|
|
9377
|
+
const total = experienceScore + expertiseScore + authoritativenessScore + trustworthinessScore;
|
|
9378
|
+
let grade = "B";
|
|
9379
|
+
if (total >= 95)
|
|
9380
|
+
grade = "A+";
|
|
9381
|
+
else if (total >= 80)
|
|
9382
|
+
grade = "A";
|
|
9383
|
+
const schemaJson = {
|
|
9384
|
+
"@context": "https://schema.org",
|
|
9385
|
+
"@type": "Person",
|
|
9386
|
+
name: authorName,
|
|
9387
|
+
jobTitle,
|
|
9388
|
+
description: bio,
|
|
9389
|
+
sameAs: sameAsUrls.length > 0 ? sameAsUrls : [
|
|
9390
|
+
`https://www.linkedin.com/in/${authorName.toLowerCase().replace(/\s+/g, "-")}`,
|
|
9391
|
+
`https://x.com/${authorName.toLowerCase().replace(/\s+/g, "")}`
|
|
9392
|
+
]
|
|
9393
|
+
};
|
|
9394
|
+
return {
|
|
9395
|
+
authorName,
|
|
9396
|
+
jobTitle,
|
|
9397
|
+
overallEeatScore: total,
|
|
9398
|
+
grade,
|
|
9399
|
+
dimensions: {
|
|
9400
|
+
experienceScore,
|
|
9401
|
+
expertiseScore,
|
|
9402
|
+
authoritativenessScore,
|
|
9403
|
+
trustworthinessScore
|
|
9404
|
+
},
|
|
9405
|
+
verifiedEntities: sameAsUrls,
|
|
9406
|
+
schemaJson
|
|
9407
|
+
};
|
|
9408
|
+
}
|
|
9409
|
+
static generateLeadMagnet(type, title, brandName = "LynxSEO") {
|
|
9410
|
+
const embeddableHtml = `<div class="lynx-lead-magnet" style="border: 2px solid #4f46e5; border-radius: 16px; padding: 24px; background: #fafafa; max-width: 520px; font-family: sans-serif;">
|
|
9411
|
+
<h3 style="margin-top: 0; color: #1e1b4b; font-size: 20px;">\uD83E\uDDF2 ${title}</h3>
|
|
9412
|
+
<p style="color: #4b5563; font-size: 14px;">Calculez votre rentabilité immédiate et recevez le rapport détaillé par email.</p>
|
|
9413
|
+
<div style="display: flex; flex-direction: column; gap: 12px; margin-top: 16px;">
|
|
9414
|
+
<input type="text" placeholder="Votre Nom ou Entreprise" style="padding: 10px 14px; border: 1px solid #d1d5db; border-radius: 8px;" />
|
|
9415
|
+
<input type="email" placeholder="votre-email@pro.com" style="padding: 10px 14px; border: 1px solid #d1d5db; border-radius: 8px;" />
|
|
9416
|
+
<button style="padding: 12px; background: #4f46e5; color: #ffffff; font-weight: bold; border: none; border-radius: 8px; cursor: pointer;">
|
|
9417
|
+
Débloquer l'Estimation Instantanée
|
|
9418
|
+
</button>
|
|
9419
|
+
</div>
|
|
9420
|
+
<div style="margin-top: 12px; font-size: 11px; color: #9ca3af; text-align: center;">⚡ Propulsé par ${brandName} Embed Widget</div>
|
|
9421
|
+
</div>`;
|
|
9422
|
+
return {
|
|
9423
|
+
leadMagnetType: type,
|
|
9424
|
+
title,
|
|
9425
|
+
ctaText: "Débloquer l'Estimation Instantanée",
|
|
9426
|
+
inputLabels: ["Entreprise", "Email Pro"],
|
|
9427
|
+
embeddableHtml
|
|
9428
|
+
};
|
|
9429
|
+
}
|
|
9430
|
+
}
|
|
9431
|
+
|
|
9432
|
+
// src/index.ts
|
|
8985
9433
|
function createLynxSeoEngine(config) {
|
|
8986
9434
|
return new LynxSeoEngine(config);
|
|
8987
9435
|
}
|
|
@@ -9027,11 +9475,15 @@ var LynxSeo = {
|
|
|
9027
9475
|
manifest: PublicRoutesManifestEngine,
|
|
9028
9476
|
knowledgeBank: KnowledgeBankBuilder,
|
|
9029
9477
|
rag: LynxRagKnowledgeEngine,
|
|
9030
|
-
translator: LynxRateLimitedTranslator
|
|
9478
|
+
translator: LynxRateLimitedTranslator,
|
|
9479
|
+
pageRankGraph: InternalPageRankEngine,
|
|
9480
|
+
geoCitation: GeoCitationScorer,
|
|
9481
|
+
marketingSkills: MarketingSkillsEngine
|
|
9031
9482
|
};
|
|
9032
9483
|
var src_default = LynxSeo;
|
|
9033
9484
|
export {
|
|
9034
9485
|
validateSeoSlug,
|
|
9486
|
+
resolveLocationFromHeaders,
|
|
9035
9487
|
resolveFeatureIcon,
|
|
9036
9488
|
resolveBuiltInLocations,
|
|
9037
9489
|
resolveBrandIcon,
|
|
@@ -9040,6 +9492,7 @@ export {
|
|
|
9040
9492
|
getSeoAgentPrompt,
|
|
9041
9493
|
src_default as default,
|
|
9042
9494
|
createLynxSeoEngine,
|
|
9495
|
+
createDynamicLocation,
|
|
9043
9496
|
cleanSeoSlug,
|
|
9044
9497
|
YoastParityEngine,
|
|
9045
9498
|
VideoYouTubeAnalyzer,
|
|
@@ -9062,7 +9515,7 @@ export {
|
|
|
9062
9515
|
RssSyndicationFeedGenerator,
|
|
9063
9516
|
RealReviewsSyncEngine,
|
|
9064
9517
|
RankMathParityEngine,
|
|
9065
|
-
|
|
9518
|
+
PublicRoutesManifestEngine,
|
|
9066
9519
|
PseoMatrixEngine,
|
|
9067
9520
|
PowerWordsPsychologyEngine,
|
|
9068
9521
|
PSEO_AGENT_SYSTEM_PROMPT,
|
|
@@ -9070,30 +9523,33 @@ export {
|
|
|
9070
9523
|
NGramDensityAnalyzer,
|
|
9071
9524
|
McpSeoServerHub,
|
|
9072
9525
|
MasterMarketingEngine,
|
|
9526
|
+
MarketingSkillsEngine,
|
|
9073
9527
|
MULTILINGUAL_STOP_WORDS,
|
|
9074
9528
|
MULTILINGUAL_POWER_WORDS,
|
|
9075
9529
|
MULTILINGUAL_DISCLAIMERS,
|
|
9076
9530
|
MULTILINGUAL_BANNED_DISPARAGING_WORDS,
|
|
9077
9531
|
LynxSeoEngine,
|
|
9078
9532
|
LynxSeo,
|
|
9079
|
-
|
|
9080
|
-
|
|
9533
|
+
LynxRateLimitedTranslator,
|
|
9534
|
+
LynxRagKnowledgeEngine,
|
|
9081
9535
|
LynxAnalyticsClient,
|
|
9082
9536
|
LlmContentCleaner,
|
|
9083
9537
|
LegalDisclaimerEngine,
|
|
9084
9538
|
LagoTokenMeter,
|
|
9085
9539
|
KnowledgeGraphLinker,
|
|
9086
|
-
|
|
9540
|
+
KnowledgeBankBuilder,
|
|
9087
9541
|
KeywordPermutatorEngine,
|
|
9088
9542
|
IsrCacheManager,
|
|
9543
|
+
InternalPageRankEngine,
|
|
9089
9544
|
InstantMatrixSearchEngine,
|
|
9090
9545
|
IndexNowClient,
|
|
9091
9546
|
I18nDetector,
|
|
9092
9547
|
HyperswitchGateway,
|
|
9093
9548
|
GoogleBusinessProfileEngine,
|
|
9094
9549
|
GeoMeshLinkingEngine,
|
|
9550
|
+
GeoCitationScorer,
|
|
9095
9551
|
FreePublicToolsEngine,
|
|
9096
|
-
|
|
9552
|
+
FeaturesKnowledgeHarvester,
|
|
9097
9553
|
ExtendedSchemaGraphBuilder,
|
|
9098
9554
|
ExistingMediaHarvester,
|
|
9099
9555
|
EmbeddableSeoWidgetGenerator,
|