@lynxflow/seo-engine 1.8.0 → 1.8.2

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/dist/index.mjs CHANGED
@@ -7232,6 +7232,354 @@ class VideoYouTubeAnalyzer {
7232
7232
  `.trim();
7233
7233
  }
7234
7234
  }
7235
+ // src/power-words-psychology.ts
7236
+ var MULTILINGUAL_POWER_WORDS = {
7237
+ fr: {
7238
+ authority: [
7239
+ "officiel",
7240
+ "guide",
7241
+ "expert",
7242
+ "complet",
7243
+ "certifié",
7244
+ "ultime",
7245
+ "meilleur",
7246
+ "meilleurs",
7247
+ "comparatif",
7248
+ "maîtriser",
7249
+ "spécialiste",
7250
+ "leader",
7251
+ "professionnel",
7252
+ "authentique",
7253
+ "infaillible",
7254
+ "reconnu",
7255
+ "démontré"
7256
+ ],
7257
+ urgency: [
7258
+ "rapide",
7259
+ "instantané",
7260
+ "maintenant",
7261
+ "immédiat",
7262
+ "express",
7263
+ "2026",
7264
+ "dernière minute",
7265
+ "urgent",
7266
+ "dépêchez-vous",
7267
+ "en 5 min",
7268
+ "en 10 min",
7269
+ "aujourd'hui",
7270
+ "débloquer"
7271
+ ],
7272
+ value: [
7273
+ "gratuit",
7274
+ "économique",
7275
+ "rentable",
7276
+ "offert",
7277
+ "sans engagement",
7278
+ "garanti",
7279
+ "facile",
7280
+ "clé en main",
7281
+ "rentabilité",
7282
+ "gain",
7283
+ "économisez",
7284
+ "inclus",
7285
+ "accessible",
7286
+ "inédit"
7287
+ ],
7288
+ curiosity: [
7289
+ "exclusif",
7290
+ "secret",
7291
+ "astuces",
7292
+ "révélé",
7293
+ "inédit",
7294
+ "top",
7295
+ "méthode",
7296
+ "pourquoi",
7297
+ "comment",
7298
+ "découvrir",
7299
+ "choc",
7300
+ "incontournable",
7301
+ "mystère",
7302
+ "incroyable"
7303
+ ],
7304
+ sentimentPositive: [
7305
+ "parfait",
7306
+ "incroyable",
7307
+ "magnifique",
7308
+ "puissant",
7309
+ "réussi",
7310
+ "génial",
7311
+ "exceptionnel",
7312
+ "facile",
7313
+ "meilleur",
7314
+ "succès",
7315
+ "brillant",
7316
+ "splendide",
7317
+ "radieux",
7318
+ "magique",
7319
+ "sublime"
7320
+ ],
7321
+ sentimentNegative: [
7322
+ "erreur",
7323
+ "piège",
7324
+ "danger",
7325
+ "éviter",
7326
+ "pire",
7327
+ "arnaque",
7328
+ "catastrophe",
7329
+ "risqué",
7330
+ "menace",
7331
+ "perte"
7332
+ ]
7333
+ },
7334
+ en: {
7335
+ authority: [
7336
+ "ultimate",
7337
+ "complete",
7338
+ "definitive",
7339
+ "guide",
7340
+ "expert",
7341
+ "official",
7342
+ "proven",
7343
+ "master",
7344
+ "certified",
7345
+ "best",
7346
+ "top",
7347
+ "authority",
7348
+ "case study",
7349
+ "benchmark",
7350
+ "professional"
7351
+ ],
7352
+ urgency: [
7353
+ "instant",
7354
+ "fast",
7355
+ "quick",
7356
+ "now",
7357
+ "today",
7358
+ "2026",
7359
+ "deadline",
7360
+ "last chance",
7361
+ "step-by-step",
7362
+ "overnight",
7363
+ "rapid",
7364
+ "minutes"
7365
+ ],
7366
+ value: [
7367
+ "free",
7368
+ "affordable",
7369
+ "guaranteed",
7370
+ "save",
7371
+ "profit",
7372
+ "profitable",
7373
+ "bonus",
7374
+ "cheap",
7375
+ "priceless",
7376
+ "effortless",
7377
+ "lifetime",
7378
+ "budget"
7379
+ ],
7380
+ curiosity: [
7381
+ "secret",
7382
+ "secrets",
7383
+ "exclusive",
7384
+ "revealed",
7385
+ "hacks",
7386
+ "tricks",
7387
+ "hacks",
7388
+ "behind the scenes",
7389
+ "uncovered",
7390
+ "surprising",
7391
+ "insider",
7392
+ "confidential",
7393
+ "jaw-dropping"
7394
+ ],
7395
+ sentimentPositive: [
7396
+ "amazing",
7397
+ "awesome",
7398
+ "brilliant",
7399
+ "epic",
7400
+ "legendary",
7401
+ "superb",
7402
+ "stunning",
7403
+ "perfect",
7404
+ "powerful",
7405
+ "triumph",
7406
+ "miracle",
7407
+ "flawless"
7408
+ ],
7409
+ sentimentNegative: [
7410
+ "mistake",
7411
+ "warning",
7412
+ "deadly",
7413
+ "worst",
7414
+ "danger",
7415
+ "toxic",
7416
+ "destroy",
7417
+ "ruin",
7418
+ "scam",
7419
+ "nightmare"
7420
+ ]
7421
+ },
7422
+ es: {
7423
+ authority: ["guía", "completo", "definitivo", "experto", "oficial", "mejor", "mejores", "certificado", "profesional", "maestro"],
7424
+ urgency: ["rápido", "ahora", "inmediato", "2026", "hoy", "urgente", "en minutos", "paso a paso"],
7425
+ value: ["gratis", "gratuito", "económico", "garantizado", "ahorra", "rentable", "oferta", "sin riesgo"],
7426
+ curiosity: ["secreto", "exclusivo", "revelado", "trucos", "increíble", "top", "método", "descubre"],
7427
+ sentimentPositive: ["increíble", "fantástico", "perfecto", "excelente", "maravilloso", "potente", "éxito"],
7428
+ sentimentNegative: ["error", "peligro", "evitar", "peor", "estafa", "trampa", "arruinar"]
7429
+ },
7430
+ de: {
7431
+ authority: ["leitfaden", "komplett", "experte", "offiziell", "beste", "bester", "zertifiziert", "vergleich", "meister"],
7432
+ urgency: ["schnell", "jetzt", "sofort", "2026", "heute", "schritt-für-schritt", "in 5 minuten"],
7433
+ value: ["kostenlos", "gratis", "sparen", "garantiert", "günstig", "rendite", "ohne risiko"],
7434
+ curiosity: ["geheim", "exklusiv", "tipps", "tricks", "enthüllt", "top", "warum", "entdecken"],
7435
+ sentimentPositive: ["perfekt", "genial", "hervorragend", "leistungsstark", "erfolg", "wunderbar"],
7436
+ sentimentNegative: ["fehler", "gefahr", "vermeiden", "schlimmste", "falle", "risiko"]
7437
+ },
7438
+ it: {
7439
+ authority: ["guida", "completa", "esperto", "ufficiale", "migliore", "migliori", "certificato", "professionale"],
7440
+ urgency: ["veloce", "ora", "subito", "2026", "oggi", "passo dopo passo", "in pochi minuti"],
7441
+ value: ["gratis", "gratuito", "economico", "garantito", "risparmio", "conveniente", "senza rischi"],
7442
+ curiosity: ["segreto", "esclusivo", "trucchi", "rivelato", "top", "metodo", "scopri"],
7443
+ sentimentPositive: ["perfetto", "fantastico", "eccellente", "potente", "successo", "incredibile"],
7444
+ sentimentNegative: ["errore", "pericolo", "evitare", "peggiore", "truffa", "trappola"]
7445
+ },
7446
+ nl: {
7447
+ authority: ["gids", "compleet", "expert", "officieel", "beste", "gecertificeerd", "professioneel"],
7448
+ urgency: ["snel", "nu", "direct", "2026", "vandaag", "stap voor stap"],
7449
+ value: ["gratis", "goedkoop", "gegarandeerd", "bespaar", "rendement", "zonder risico"],
7450
+ curiosity: ["geheim", "exclusief", "tips", "onthuld", "top", "ontdek"],
7451
+ sentimentPositive: ["perfect", "geweldig", "uitstekend", "krachtig", "succes"],
7452
+ sentimentNegative: ["fout", "gevaar", "vermijden", "slechtste", "valkuil"]
7453
+ },
7454
+ pt: {
7455
+ authority: ["guia", "completo", "definitivo", "especialista", "oficial", "melhor", "melhores", "certificado"],
7456
+ urgency: ["rápido", "agora", "imediato", "2026", "hoje", "passo a passo"],
7457
+ value: ["grátis", "gratuito", "econômico", "garantido", "economize", "sem risco"],
7458
+ curiosity: ["segredo", "exclusivo", "revelado", "truques", "top", "descubra"],
7459
+ sentimentPositive: ["incrível", "perfeito", "excelente", "poderoso", "sucesso"],
7460
+ sentimentNegative: ["erro", "perigo", "evitar", "pior", "golpe"]
7461
+ }
7462
+ };
7463
+
7464
+ class PowerWordsPsychologyEngine {
7465
+ static analyzeTitlePsychology(title, lang = "fr") {
7466
+ const cleanTitle = title.toLowerCase();
7467
+ const dict = MULTILINGUAL_POWER_WORDS[lang] || MULTILINGUAL_POWER_WORDS.fr;
7468
+ const detectedPowerWords = [];
7469
+ let score = 30;
7470
+ const hasAuthority = dict.authority.some((w) => {
7471
+ if (cleanTitle.includes(w)) {
7472
+ detectedPowerWords.push(w);
7473
+ return true;
7474
+ }
7475
+ return false;
7476
+ });
7477
+ if (hasAuthority)
7478
+ score += 20;
7479
+ const hasUrgency = dict.urgency.some((w) => {
7480
+ if (cleanTitle.includes(w)) {
7481
+ detectedPowerWords.push(w);
7482
+ return true;
7483
+ }
7484
+ return false;
7485
+ });
7486
+ if (hasUrgency)
7487
+ score += 15;
7488
+ const hasValue = dict.value.some((w) => {
7489
+ if (cleanTitle.includes(w)) {
7490
+ detectedPowerWords.push(w);
7491
+ return true;
7492
+ }
7493
+ return false;
7494
+ });
7495
+ if (hasValue)
7496
+ score += 15;
7497
+ const hasCuriosity = dict.curiosity.some((w) => {
7498
+ if (cleanTitle.includes(w)) {
7499
+ detectedPowerWords.push(w);
7500
+ return true;
7501
+ }
7502
+ return false;
7503
+ });
7504
+ if (hasCuriosity)
7505
+ score += 10;
7506
+ const hasNumber = /\d+/.test(title);
7507
+ if (hasNumber)
7508
+ score += 10;
7509
+ const currentYear = new Date().getFullYear().toString();
7510
+ const hasYear = title.includes(currentYear) || title.includes("2026");
7511
+ let sentiment = "neutre";
7512
+ const hasPositive = dict.sentimentPositive.some((w) => cleanTitle.includes(w));
7513
+ const hasNegative = dict.sentimentNegative.some((w) => cleanTitle.includes(w));
7514
+ if (hasPositive) {
7515
+ sentiment = "positif";
7516
+ } else if (hasNegative) {
7517
+ sentiment = "negatif";
7518
+ }
7519
+ const recommendations = [];
7520
+ if (!detectedPowerWords.length) {
7521
+ recommendations.push("Ajoutez au moins un mot d'impact (*Power Word*) comme 'Guide Complet', 'Meilleur' ou 'Ultime'.");
7522
+ }
7523
+ if (!hasNumber) {
7524
+ recommendations.push("Intégrez un chiffre ou l'année en cours (ex: '7 astuces', '2026') pour booster le taux de clic de +36%.");
7525
+ }
7526
+ if (title.length < 35) {
7527
+ recommendations.push("Titre trop court : enrichissez votre promesse de valeur pour occuper les 600px de la SERP Google.");
7528
+ }
7529
+ const suggestedTitles = [];
7530
+ if (lang === "fr") {
7531
+ suggestedTitles.push(`${title} : Guide Ultime 2026`);
7532
+ suggestedTitles.push(`Les 5 Meilleurs ${title} (Comparatif & Avis)`);
7533
+ suggestedTitles.push(`${title} — Solution Rapide & Complète`);
7534
+ } else {
7535
+ suggestedTitles.push(`${title}: The Ultimate 2026 Guide`);
7536
+ suggestedTitles.push(`Top 5 Best ${title} (Full Review & Comparison)`);
7537
+ suggestedTitles.push(`${title} — Proven & Fast Method`);
7538
+ }
7539
+ return {
7540
+ score: Math.min(100, score),
7541
+ powerWordsDetected: Array.from(new Set(detectedPowerWords)),
7542
+ sentiment,
7543
+ hasNumber,
7544
+ hasYear,
7545
+ hasCuriosityTrigger: hasCuriosity,
7546
+ hasUrgencyTrigger: hasUrgency,
7547
+ hasAuthorityTrigger: hasAuthority,
7548
+ recommendations,
7549
+ suggestedTitles
7550
+ };
7551
+ }
7552
+ static enrichProgrammaticTitle(service, locationOrCompetitor, type = "geo", lang = "fr") {
7553
+ const year = "2026";
7554
+ if (lang === "fr") {
7555
+ if (type === "geo") {
7556
+ return `Meilleur ${service} à ${locationOrCompetitor} : Guide Complet ${year}`;
7557
+ } else if (type === "vs") {
7558
+ return `${service} vs ${locationOrCompetitor} : Le Comparatif Ultime & Avis`;
7559
+ } else {
7560
+ return `Top 5 Alternatives à ${locationOrCompetitor} : Comparatif ${year}`;
7561
+ }
7562
+ } else if (lang === "en") {
7563
+ if (type === "geo") {
7564
+ return `Best ${service} in ${locationOrCompetitor}: Ultimate ${year} Guide`;
7565
+ } else if (type === "vs") {
7566
+ return `${service} vs ${locationOrCompetitor}: Definitive Comparison`;
7567
+ } else {
7568
+ return `Top 5 Alternatives to ${locationOrCompetitor} (${year} Review)`;
7569
+ }
7570
+ } else if (lang === "es") {
7571
+ if (type === "geo") {
7572
+ return `Mejor ${service} en ${locationOrCompetitor}: Guía Completa ${year}`;
7573
+ } else {
7574
+ return `${service} vs ${locationOrCompetitor}: Comparativa Definitiva`;
7575
+ }
7576
+ } else if (lang === "de") {
7577
+ return `Beste ${service} in ${locationOrCompetitor}: Kompletter Leitfaden ${year}`;
7578
+ } else {
7579
+ return `${service} in ${locationOrCompetitor} (${year})`;
7580
+ }
7581
+ }
7582
+ }
7235
7583
  // src/index.ts
7236
7584
  function createLynxSeoEngine(config) {
7237
7585
  return new LynxSeoEngine(config);
@@ -7310,12 +7658,14 @@ export {
7310
7658
  RealReviewsSyncEngine,
7311
7659
  RankMathParityEngine,
7312
7660
  PseoMatrixEngine,
7661
+ PowerWordsPsychologyEngine,
7313
7662
  PSEO_AGENT_SYSTEM_PROMPT,
7314
7663
  OgImageGenerator,
7315
7664
  NGramDensityAnalyzer,
7316
7665
  McpSeoServerHub,
7317
7666
  MasterMarketingEngine,
7318
7667
  MULTILINGUAL_STOP_WORDS,
7668
+ MULTILINGUAL_POWER_WORDS,
7319
7669
  MULTILINGUAL_DISCLAIMERS,
7320
7670
  MULTILINGUAL_BANNED_DISPARAGING_WORDS,
7321
7671
  LynxSeoEngine,
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 🧠 Multilingual Power Words & Click Psychology Engine
3
+ * High-Converting CTR Optimizers & Sentiment Analysis across FR, EN, ES, DE, IT
4
+ */
5
+ export type LanguageCode = "fr" | "en" | "es" | "de" | "it" | "nl" | "pt";
6
+ export interface PsychologyAnalysisResult {
7
+ score: number;
8
+ powerWordsDetected: string[];
9
+ sentiment: "positif" | "negatif" | "neutre";
10
+ hasNumber: boolean;
11
+ hasYear: boolean;
12
+ hasCuriosityTrigger: boolean;
13
+ hasUrgencyTrigger: boolean;
14
+ hasAuthorityTrigger: boolean;
15
+ recommendations: string[];
16
+ suggestedTitles: string[];
17
+ }
18
+ export declare const MULTILINGUAL_POWER_WORDS: Record<LanguageCode, {
19
+ authority: string[];
20
+ urgency: string[];
21
+ value: string[];
22
+ curiosity: string[];
23
+ sentimentPositive: string[];
24
+ sentimentNegative: string[];
25
+ }>;
26
+ export declare class PowerWordsPsychologyEngine {
27
+ /**
28
+ * Analyzes headline/title psychology, CTR triggers, sentiment, and Google SERP potential
29
+ */
30
+ static analyzeTitlePsychology(title: string, lang?: LanguageCode): PsychologyAnalysisResult;
31
+ /**
32
+ * Automatically enriches a programmatic title with high-converting click psychology power words
33
+ */
34
+ static enrichProgrammaticTitle(service: string, locationOrCompetitor: string, type?: "geo" | "vs" | "alt", lang?: LanguageCode): string;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynxflow/seo-engine",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "High-Performance Multilingual Programmatic SEO & AI Search Engine SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/index.ts CHANGED
@@ -65,6 +65,7 @@ export * from "./team-rbac";
65
65
  export * from "./real-reviews-sync";
66
66
  export * from "./google-business-profile";
67
67
  export * from "./video-youtube-analyzer";
68
+ export * from "./power-words-psychology";
68
69
 
69
70
  import { LynxSeoEngine, type EngineConfig } from "./engine";
70
71
  import { ApiKeyGuardian } from "./auth-key";
@@ -0,0 +1,260 @@
1
+ /**
2
+ * 🧠 Multilingual Power Words & Click Psychology Engine
3
+ * High-Converting CTR Optimizers & Sentiment Analysis across FR, EN, ES, DE, IT
4
+ */
5
+
6
+ export type LanguageCode = "fr" | "en" | "es" | "de" | "it" | "nl" | "pt";
7
+
8
+ export interface PsychologyAnalysisResult {
9
+ score: number; // 0 to 100
10
+ powerWordsDetected: string[];
11
+ sentiment: "positif" | "negatif" | "neutre";
12
+ hasNumber: boolean;
13
+ hasYear: boolean;
14
+ hasCuriosityTrigger: boolean;
15
+ hasUrgencyTrigger: boolean;
16
+ hasAuthorityTrigger: boolean;
17
+ recommendations: string[];
18
+ suggestedTitles: string[];
19
+ }
20
+
21
+ export const MULTILINGUAL_POWER_WORDS: Record<LanguageCode, {
22
+ authority: string[];
23
+ urgency: string[];
24
+ value: string[];
25
+ curiosity: string[];
26
+ sentimentPositive: string[];
27
+ sentimentNegative: string[];
28
+ }> = {
29
+ fr: {
30
+ authority: [
31
+ "officiel", "guide", "expert", "complet", "certifié", "ultime", "meilleur", "meilleurs", "comparatif",
32
+ "maîtriser", "spécialiste", "leader", "professionnel", "authentique", "infaillible", "reconnu", "démontré"
33
+ ],
34
+ urgency: [
35
+ "rapide", "instantané", "maintenant", "immédiat", "express", "2026", "dernière minute", "urgent",
36
+ "dépêchez-vous", "en 5 min", "en 10 min", "aujourd'hui", "débloquer"
37
+ ],
38
+ value: [
39
+ "gratuit", "économique", "rentable", "offert", "sans engagement", "garanti", "facile", "clé en main",
40
+ "rentabilité", "gain", "économisez", "inclus", "accessible", "inédit"
41
+ ],
42
+ curiosity: [
43
+ "exclusif", "secret", "astuces", "révélé", "inédit", "top", "méthode", "pourquoi", "comment",
44
+ "découvrir", "choc", "incontournable", "mystère", "incroyable"
45
+ ],
46
+ sentimentPositive: [
47
+ "parfait", "incroyable", "magnifique", "puissant", "réussi", "génial", "exceptionnel", "facile",
48
+ "meilleur", "succès", "brillant", "splendide", "radieux", "magique", "sublime"
49
+ ],
50
+ sentimentNegative: [
51
+ "erreur", "piège", "danger", "éviter", "pire", "arnaque", "catastrophe", "risqué", "menace", "perte"
52
+ ]
53
+ },
54
+ en: {
55
+ authority: [
56
+ "ultimate", "complete", "definitive", "guide", "expert", "official", "proven", "master", "certified",
57
+ "best", "top", "authority", "case study", "benchmark", "professional"
58
+ ],
59
+ urgency: [
60
+ "instant", "fast", "quick", "now", "today", "2026", "deadline", "last chance", "step-by-step",
61
+ "overnight", "rapid", "minutes"
62
+ ],
63
+ value: [
64
+ "free", "affordable", "guaranteed", "save", "profit", "profitable", "bonus", "cheap", "priceless",
65
+ "effortless", "lifetime", "budget"
66
+ ],
67
+ curiosity: [
68
+ "secret", "secrets", "exclusive", "revealed", "hacks", "tricks", "hacks", "behind the scenes",
69
+ "uncovered", "surprising", "insider", "confidential", "jaw-dropping"
70
+ ],
71
+ sentimentPositive: [
72
+ "amazing", "awesome", "brilliant", "epic", "legendary", "superb", "stunning", "perfect", "powerful",
73
+ "triumph", "miracle", "flawless"
74
+ ],
75
+ sentimentNegative: [
76
+ "mistake", "warning", "deadly", "worst", "danger", "toxic", "destroy", "ruin", "scam", "nightmare"
77
+ ]
78
+ },
79
+ es: {
80
+ authority: ["guía", "completo", "definitivo", "experto", "oficial", "mejor", "mejores", "certificado", "profesional", "maestro"],
81
+ urgency: ["rápido", "ahora", "inmediato", "2026", "hoy", "urgente", "en minutos", "paso a paso"],
82
+ value: ["gratis", "gratuito", "económico", "garantizado", "ahorra", "rentable", "oferta", "sin riesgo"],
83
+ curiosity: ["secreto", "exclusivo", "revelado", "trucos", "increíble", "top", "método", "descubre"],
84
+ sentimentPositive: ["increíble", "fantástico", "perfecto", "excelente", "maravilloso", "potente", "éxito"],
85
+ sentimentNegative: ["error", "peligro", "evitar", "peor", "estafa", "trampa", "arruinar"]
86
+ },
87
+ de: {
88
+ authority: ["leitfaden", "komplett", "experte", "offiziell", "beste", "bester", "zertifiziert", "vergleich", "meister"],
89
+ urgency: ["schnell", "jetzt", "sofort", "2026", "heute", "schritt-für-schritt", "in 5 minuten"],
90
+ value: ["kostenlos", "gratis", "sparen", "garantiert", "günstig", "rendite", "ohne risiko"],
91
+ curiosity: ["geheim", "exklusiv", "tipps", "tricks", "enthüllt", "top", "warum", "entdecken"],
92
+ sentimentPositive: ["perfekt", "genial", "hervorragend", "leistungsstark", "erfolg", "wunderbar"],
93
+ sentimentNegative: ["fehler", "gefahr", "vermeiden", "schlimmste", "falle", "risiko"]
94
+ },
95
+ it: {
96
+ authority: ["guida", "completa", "esperto", "ufficiale", "migliore", "migliori", "certificato", "professionale"],
97
+ urgency: ["veloce", "ora", "subito", "2026", "oggi", "passo dopo passo", "in pochi minuti"],
98
+ value: ["gratis", "gratuito", "economico", "garantito", "risparmio", "conveniente", "senza rischi"],
99
+ curiosity: ["segreto", "esclusivo", "trucchi", "rivelato", "top", "metodo", "scopri"],
100
+ sentimentPositive: ["perfetto", "fantastico", "eccellente", "potente", "successo", "incredibile"],
101
+ sentimentNegative: ["errore", "pericolo", "evitare", "peggiore", "truffa", "trappola"]
102
+ },
103
+ nl: {
104
+ authority: ["gids", "compleet", "expert", "officieel", "beste", "gecertificeerd", "professioneel"],
105
+ urgency: ["snel", "nu", "direct", "2026", "vandaag", "stap voor stap"],
106
+ value: ["gratis", "goedkoop", "gegarandeerd", "bespaar", "rendement", "zonder risico"],
107
+ curiosity: ["geheim", "exclusief", "tips", "onthuld", "top", "ontdek"],
108
+ sentimentPositive: ["perfect", "geweldig", "uitstekend", "krachtig", "succes"],
109
+ sentimentNegative: ["fout", "gevaar", "vermijden", "slechtste", "valkuil"]
110
+ },
111
+ pt: {
112
+ authority: ["guia", "completo", "definitivo", "especialista", "oficial", "melhor", "melhores", "certificado"],
113
+ urgency: ["rápido", "agora", "imediato", "2026", "hoje", "passo a passo"],
114
+ value: ["grátis", "gratuito", "econômico", "garantido", "economize", "sem risco"],
115
+ curiosity: ["segredo", "exclusivo", "revelado", "truques", "top", "descubra"],
116
+ sentimentPositive: ["incrível", "perfeito", "excelente", "poderoso", "sucesso"],
117
+ sentimentNegative: ["erro", "perigo", "evitar", "pior", "golpe"]
118
+ }
119
+ };
120
+
121
+ export class PowerWordsPsychologyEngine {
122
+ /**
123
+ * Analyzes headline/title psychology, CTR triggers, sentiment, and Google SERP potential
124
+ */
125
+ static analyzeTitlePsychology(title: string, lang: LanguageCode = "fr"): PsychologyAnalysisResult {
126
+ const cleanTitle = title.toLowerCase();
127
+ const dict = MULTILINGUAL_POWER_WORDS[lang] || MULTILINGUAL_POWER_WORDS.fr;
128
+
129
+ const detectedPowerWords: string[] = [];
130
+ let score = 30; // base score
131
+
132
+ // 1. Check Authority Triggers
133
+ const hasAuthority = dict.authority.some(w => {
134
+ if (cleanTitle.includes(w)) {
135
+ detectedPowerWords.push(w);
136
+ return true;
137
+ }
138
+ return false;
139
+ });
140
+ if (hasAuthority) score += 20;
141
+
142
+ // 2. Check Urgency & Timeliness Triggers
143
+ const hasUrgency = dict.urgency.some(w => {
144
+ if (cleanTitle.includes(w)) {
145
+ detectedPowerWords.push(w);
146
+ return true;
147
+ }
148
+ return false;
149
+ });
150
+ if (hasUrgency) score += 15;
151
+
152
+ // 3. Check Value Triggers
153
+ const hasValue = dict.value.some(w => {
154
+ if (cleanTitle.includes(w)) {
155
+ detectedPowerWords.push(w);
156
+ return true;
157
+ }
158
+ return false;
159
+ });
160
+ if (hasValue) score += 15;
161
+
162
+ // 4. Check Curiosity & Exclusivity Triggers
163
+ const hasCuriosity = dict.curiosity.some(w => {
164
+ if (cleanTitle.includes(w)) {
165
+ detectedPowerWords.push(w);
166
+ return true;
167
+ }
168
+ return false;
169
+ });
170
+ if (hasCuriosity) score += 10;
171
+
172
+ // 5. Check Number & Current Year (BuzzSumo & Conductor: +36% CTR)
173
+ const hasNumber = /\d+/.test(title);
174
+ if (hasNumber) score += 10;
175
+
176
+ const currentYear = new Date().getFullYear().toString();
177
+ const hasYear = title.includes(currentYear) || title.includes("2026");
178
+
179
+ // 6. Sentiment Detection
180
+ let sentiment: "positif" | "negatif" | "neutre" = "neutre";
181
+ const hasPositive = dict.sentimentPositive.some(w => cleanTitle.includes(w));
182
+ const hasNegative = dict.sentimentNegative.some(w => cleanTitle.includes(w));
183
+ if (hasPositive) {
184
+ sentiment = "positif";
185
+ } else if (hasNegative) {
186
+ sentiment = "negatif";
187
+ }
188
+
189
+ // 7. Recommendations
190
+ const recommendations: string[] = [];
191
+ if (!detectedPowerWords.length) {
192
+ recommendations.push("Ajoutez au moins un mot d'impact (*Power Word*) comme 'Guide Complet', 'Meilleur' ou 'Ultime'.");
193
+ }
194
+ if (!hasNumber) {
195
+ recommendations.push("Intégrez un chiffre ou l'année en cours (ex: '7 astuces', '2026') pour booster le taux de clic de +36%.");
196
+ }
197
+ if (title.length < 35) {
198
+ recommendations.push("Titre trop court : enrichissez votre promesse de valeur pour occuper les 600px de la SERP Google.");
199
+ }
200
+
201
+ // 8. Dynamic High-CTR Suggestions Generator
202
+ const suggestedTitles: string[] = [];
203
+ if (lang === "fr") {
204
+ suggestedTitles.push(`${title} : Guide Ultime 2026`);
205
+ suggestedTitles.push(`Les 5 Meilleurs ${title} (Comparatif & Avis)`);
206
+ suggestedTitles.push(`${title} — Solution Rapide & Complète`);
207
+ } else {
208
+ suggestedTitles.push(`${title}: The Ultimate 2026 Guide`);
209
+ suggestedTitles.push(`Top 5 Best ${title} (Full Review & Comparison)`);
210
+ suggestedTitles.push(`${title} — Proven & Fast Method`);
211
+ }
212
+
213
+ return {
214
+ score: Math.min(100, score),
215
+ powerWordsDetected: Array.from(new Set(detectedPowerWords)),
216
+ sentiment,
217
+ hasNumber,
218
+ hasYear,
219
+ hasCuriosityTrigger: hasCuriosity,
220
+ hasUrgencyTrigger: hasUrgency,
221
+ hasAuthorityTrigger: hasAuthority,
222
+ recommendations,
223
+ suggestedTitles
224
+ };
225
+ }
226
+
227
+ /**
228
+ * Automatically enriches a programmatic title with high-converting click psychology power words
229
+ */
230
+ static enrichProgrammaticTitle(service: string, locationOrCompetitor: string, type: "geo" | "vs" | "alt" = "geo", lang: LanguageCode = "fr"): string {
231
+ const year = "2026";
232
+ if (lang === "fr") {
233
+ if (type === "geo") {
234
+ return `Meilleur ${service} à ${locationOrCompetitor} : Guide Complet ${year}`;
235
+ } else if (type === "vs") {
236
+ return `${service} vs ${locationOrCompetitor} : Le Comparatif Ultime & Avis`;
237
+ } else {
238
+ return `Top 5 Alternatives à ${locationOrCompetitor} : Comparatif ${year}`;
239
+ }
240
+ } else if (lang === "en") {
241
+ if (type === "geo") {
242
+ return `Best ${service} in ${locationOrCompetitor}: Ultimate ${year} Guide`;
243
+ } else if (type === "vs") {
244
+ return `${service} vs ${locationOrCompetitor}: Definitive Comparison`;
245
+ } else {
246
+ return `Top 5 Alternatives to ${locationOrCompetitor} (${year} Review)`;
247
+ }
248
+ } else if (lang === "es") {
249
+ if (type === "geo") {
250
+ return `Mejor ${service} en ${locationOrCompetitor}: Guía Completa ${year}`;
251
+ } else {
252
+ return `${service} vs ${locationOrCompetitor}: Comparativa Definitiva`;
253
+ }
254
+ } else if (lang === "de") {
255
+ return `Beste ${service} in ${locationOrCompetitor}: Kompletter Leitfaden ${year}`;
256
+ } else {
257
+ return `${service} in ${locationOrCompetitor} (${year})`;
258
+ }
259
+ }
260
+ }