SEO ou AEO : comment être visible dans les réponses générées par l’IA
Le référencement évolue. Après le SEO, un nouveau terme s’impose progressivement : AEO (Answer Engine Optimization) . Son objectif : optimiser votre site pour apparaître non seulement dans les résultats de recherche, mais aussi dans les réponses générées par les moteurs alimentés par l’intelligence artificielle.
Pour les entreprises, cela change une chose essentielle : il ne suffit plus d’être bien positionné, il faut aussi devenir une réponse recommandée.
1. Quelle différence entre SEO et AEO ?
Le SEO améliore votre visibilité dans les moteurs de recherche traditionnels. L’AEO vise à rendre vos contenus compréhensibles, fiables et facilement citables dans les réponses générées par IA.
Aujourd’hui, les deux approches se complètent et renforcent votre visibilité digitale.
2. Pourquoi l’AEO devient stratégique
De plus en plus d’utilisateurs posent des questions complètes à des assistants IA plutôt que de cliquer sur plusieurs résultats.
Être cité dans ces réponses peut devenir un levier majeur de trafic qualifié et d’autorité.
- Répondre aux intentions de recherche
- Créer du contenu expert structuré
- Renforcer les signaux de confiance
- Optimiser les standards émergents comme llms.txt
3. Comment optimiser votre site pour le SEO et l’AEO
Les sites les mieux positionnés demain seront ceux qui combinent référencement naturel, structure sémantique, contenu expert et préparation aux moteurs conversationnels.
Le SEO attire, l’AEO fait recommander.
Conclusion
Travailler votre visibilité pour les moteurs de recherche IA aujourd’hui, c’est préparer votre acquisition digitale de demain.
🚀 Guide de configuration (3 étapes simples)
📊 Étape 1 : Créer le Google Sheet
- Créez un nouveau Google Sheet
- Nommez-le :
Commentaires Blog - Créez ces colonnes dans la première ligne :
- ✓ A1: name
- ✓ B1: email
- ✓ C1: comment
- ✓ D1: page_url
- ✓ E1: page_title
- ✓ F1: timestamp
- ✓ G1: status
- ✓ H1: Logs
- ✓ I1: custom_fields
- ✓ J1: moderation_flags
- ✓ K1: reports_count
- ✓ L1: reports_details
- ✓ M1: reports_last_date
- ✓ N1: comment_id (unique)
⚙️ Étape 2 : Configurer Google Apps Script (Code v4 FINAL — signalement corrigé)
- Dans votre Google Sheet, allez dans Extensions → Apps Script
- Supprimez le code par défaut
- Copiez-collez le code ci-dessous 👇
// ============================================================
// WIDGET BLOG COMMENTS — Google Apps Script v4
// CORRECTIONS v4 :
// - handleReport ne crée JAMAIS de nouvelle ligne
// - Recherche du commentaire par comment_id (col N)
// ET par timestamp (col F) en fallback
// - Email envoyé même si comment_id introuvable
// (signalement orphelin stocké dans feuille "Signalements")
// - Logs ultra-détaillés pour diagnostic
// ============================================================
function doPost(e) {
try {
// Compatible avec Content-Type: text/plain ET application/json
// (le widget envoie text/plain pour contourner la restriction no-cors)
const rawBody = e.postData ? e.postData.contents : '';
Logger.log('📨 Body brut reçu: ' + rawBody.substring(0, 200));
if (!rawBody || rawBody.trim() === '') {
Logger.log('❌ Body vide reçu');
return jsonResponse({ status: 'error', message: 'Body vide' });
}
const data = JSON.parse(rawBody);
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (!data || typeof data !== 'object') {
return jsonResponse({ status: 'error', message: 'Données invalides' });
}
Logger.log('✅ Action reçue: ' + (data.action || 'new_comment'));
if (data.action === 'report') {
return handleReport(data, sheet);
}
return handleNewComment(data, sheet);
} catch (error) {
Logger.log('❌ Erreur doPost: ' + error.toString());
return jsonResponse({ status: 'error', message: error.toString() });
}
}
// ------------------------------------------------------------
// NOUVEAU COMMENTAIRE
// ------------------------------------------------------------
function handleNewComment(data, sheet) {
const customFieldsJson = data.custom_fields || '';
const moderationFlags = data.moderation_flags || '';
const commentId = Utilities.getUuid();
const row = [
data.name || '',
data.email || '',
data.comment || '',
data.page_url || '',
data.page_title || '',
data.timestamp || new Date().toISOString(),
data.status || 'pending',
'', // Logs
customFieldsJson,
moderationFlags,
0, // reports_count (col K)
'', // reports_details (col L)
'', // reports_last_date (col M)
commentId // comment_id (col N)
];
sheet.appendRow(row);
Logger.log('✅ Nouveau commentaire ajouté | id=' + commentId);
if (data.enable_notification && data.admin_email) {
sendAdminNotification(data, moderationFlags);
}
return jsonResponse({
status: 'success',
message: 'Commentaire enregistré',
comment_id: commentId
});
}
// ------------------------------------------------------------
// SIGNALEMENT — NE CRÉE JAMAIS DE NOUVELLE LIGNE
// ------------------------------------------------------------
function handleReport(data, sheet) {
Logger.log('════════════════════════════════════════════');
Logger.log('🚩 handleReport v4 — début');
Logger.log('📦 Données reçues: ' + JSON.stringify(data));
Logger.log('════════════════════════════════════════════');
const reporterName = data.reporter_name || 'Anonyme';
const reporterEmail = data.reporter_email || 'Non fourni';
const reportReason = data.report_reason || 'Non spécifié';
const reportDetails = data.report_details || 'Aucun détail';
const reportDate = new Date().toISOString();
const commentId = (data.comment_id || '').toString().trim();
const adminEmail = (data.admin_email || '').toString().trim();
Logger.log('🔑 comment_id reçu: "' + commentId + '"');
Logger.log('📧 admin_email reçu: "' + adminEmail + '"');
// ── Chercher la ligne du commentaire ──────────────────────
const allValues = sheet.getDataRange().getValues();
let commentRow = -1;
if (commentId !== '') {
// Priorité : recherche par comment_id (col N = index 13)
Logger.log('🔍 Recherche par comment_id dans colonne N (' + allValues.length + ' lignes)...');
for (let i = 1; i < allValues.length; i++) {
const cellId = (allValues[i][13] || '').toString().trim();
Logger.log(' Ligne ' + (i+1) + ': "' + cellId + '"');
if (cellId === commentId) {
commentRow = i + 1;
Logger.log('✅ Trouvé par comment_id à la ligne ' + commentRow);
break;
}
}
}
// Fallback : recherche par timestamp (col F = index 5)
if (commentRow === -1 && data.comment_timestamp) {
Logger.log('🔍 Fallback: recherche par timestamp...');
const ts = (data.comment_timestamp || '').toString().trim();
for (let i = 1; i < allValues.length; i++) {
if ((allValues[i][5] || '').toString().trim() === ts) {
commentRow = i + 1;
Logger.log('✅ Trouvé par timestamp à la ligne ' + commentRow);
break;
}
}
}
// ── Mettre à jour la ligne (si trouvée) ───────────────────
let newCount = 1;
if (commentRow !== -1) {
const currentCount = parseInt(sheet.getRange(commentRow, 11).getValue()) || 0;
const currentDetails = sheet.getRange(commentRow, 12).getValue() || '';
newCount = currentCount + 1;
sheet.getRange(commentRow, 11).setValue(newCount);
Logger.log('✅ reports_count mis à jour: ' + currentCount + ' → ' + newCount);
const detailLine = '[' + reportDate + '] Par: ' + reporterName +
' (' + reporterEmail + ') | Raison: ' + reportReason +
' | Détails: ' + reportDetails;
const newDetails = currentDetails ? currentDetails + '\n\n' + detailLine : detailLine;
sheet.getRange(commentRow, 12).setValue(newDetails);
sheet.getRange(commentRow, 13).setValue(reportDate);
Logger.log('✅ Détails et date mis à jour');
} else {
// Commentaire introuvable — on NE crée PAS de nouvelle ligne
Logger.log('⚠️ Commentaire introuvable. Enregistrement dans feuille "Signalements".');
enregistrerSignalementOrphelin(data, reporterName, reporterEmail, reportReason, reportDetails, reportDate);
}
// ── Envoyer l'email admin ─────────────────────────────────
if (adminEmail !== '') {
Logger.log('📧 Envoi email signalement à: ' + adminEmail);
try {
sendReportNotification(data, newCount, reporterName, reporterEmail, reportReason, reportDetails, commentRow);
Logger.log('✅ Email signalement envoyé');
} catch (emailError) {
Logger.log('❌ Erreur envoi email: ' + emailError.toString());
}
} else {
Logger.log('⚠️ Aucun email admin configuré.');
Logger.log(' → Vérifiez le champ "Email admin pour signalements" dans le content editor du widget.');
Logger.log(' → Ou remplissez le champ "Email de l\'administrateur" (notifications générales).');
}
Logger.log('🚩 handleReport v4 — fin');
Logger.log('════════════════════════════════════════════');
return jsonResponse({
status: 'success',
message: 'Signalement traité',
reports_count: newCount,
row_updated: commentRow
});
}
// Sauvegarde orpheline si le commentaire est introuvable dans le Sheet
function enregistrerSignalementOrphelin(data, reporterName, reporterEmail, reportReason, reportDetails, reportDate) {
try {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let feuille = ss.getSheetByName('Signalements');
if (!feuille) {
feuille = ss.insertSheet('Signalements');
feuille.appendRow(['date', 'comment_id', 'comment_text', 'reporter_name', 'reporter_email', 'reason', 'details']);
}
feuille.appendRow([
reportDate,
data.comment_id || '',
data.comment_text || '',
reporterName,
reporterEmail,
reportReason,
reportDetails
]);
Logger.log('✅ Signalement orphelin enregistré dans "Signalements"');
} catch (err) {
Logger.log('❌ Erreur enregistrement orphelin: ' + err.toString());
}
}
// ------------------------------------------------------------
// EMAILS
// ------------------------------------------------------------
function sendAdminNotification(data, moderationFlags) {
try {
const subject = '📧 Nouveau commentaire sur "' + data.page_title + '"';
const body =
'Un nouveau commentaire a été posté sur votre site :\n\n' +
'👤 Nom : ' + (data.name || '') + '\n' +
'📧 Email : ' + (data.email || 'Non fourni') + '\n' +
'📄 Page : ' + (data.page_title || '') + '\n' +
'🔗 URL : ' + (data.page_url || '') + '\n' +
'📅 Date : ' + (data.timestamp || '') + '\n' +
'✅ Statut : ' + (data.status || '') + '\n\n' +
'💬 Commentaire :\n' + (data.comment || '') + '\n\n' +
(moderationFlags ? '🚨 Modération : ' + moderationFlags + '\n\n' : '') +
'---\nAccédez à votre Google Sheet pour gérer ce commentaire.';
MailApp.sendEmail(data.admin_email, subject, body);
Logger.log('✅ Email nouveau commentaire envoyé');
} catch (error) {
Logger.log('❌ Erreur envoi email commentaire: ' + error.toString());
}
}
function sendReportNotification(data, reportsCount, reporterName, reporterEmail, reportReason, reportDetails, rowUpdated) {
const subject = '🚩 SIGNALEMENT — "' + (data.page_title || 'Page inconnue') + '"';
const rowInfo = rowUpdated !== -1
? 'Ligne mise à jour dans le Sheet : ' + rowUpdated
: '⚠️ Commentaire introuvable dans le Sheet (voir feuille "Signalements")';
const body =
'🚨 ALERTE SIGNALEMENT 🚨\n\n' +
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' +
'📊 Total signalements : ' + reportsCount + '\n' +
rowInfo + '\n' +
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n' +
'💬 COMMENTAIRE SIGNALÉ\n' +
'📄 Page : ' + (data.page_title || 'N/A') + '\n' +
'🔗 URL : ' + (data.comment_page_url || 'N/A') + '\n' +
'👤 Auteur : ' + (data.comment_name || 'N/A') + '\n' +
'📧 Email auteur : ' + (data.comment_email || 'Non fourni') + '\n' +
'🔑 comment_id : ' + (data.comment_id || 'Non fourni') + '\n\n' +
'📝 Texte :\n"' + (data.comment_text || '') + '"\n\n' +
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n' +
'🚩 SIGNALÉ PAR\n' +
'👤 Nom : ' + reporterName + '\n' +
'📧 Email : ' + reporterEmail + '\n' +
'🚫 Raison : ' + reportReason + '\n' +
'📋 Détails : ' + reportDetails + '\n\n' +
'━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' +
'⚠️ Veuillez vérifier ce commentaire dans votre Google Sheet.';
MailApp.sendEmail(data.admin_email, subject, body);
Logger.log('✅ Email signalement envoyé à ' + data.admin_email);
}
// ------------------------------------------------------------
// HELPER
// ------------------------------------------------------------
function jsonResponse(obj) {
return ContentService
.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}
- Cliquez sur 💾 Enregistrer
- ⚠️ IMPORTANT : Cliquez sur "Déployer" → "Gérer les déploiements"
- Cliquez sur ✏️ (Modifier) à côté du déploiement existant
- Changez "Version" → "Nouvelle version"
- Cliquez sur "Déployer"
- ✅ Votre webhook est maintenant mis à jour !
🔍 Pour voir les logs de débogage :
- Dans Google Apps Script, cliquez sur "Exécutions"(icône horloge)
- Cliquez sur la dernière exécution
- Vous verrez tous les logs détaillés du traitement du signalement
🔗 Étape 3 : Connecter à vos Collections
- Dans votre site, allez dans Collections
- Cliquez sur "Connect to Google Sheets"
- Autorisez et sélectionnez votre Google Sheet
- Configurez le mapping des colonnes
- Activez la synchronisation bidirectionnelle automatique
- Notez le nom de la collection créée
- Mettez à jour le champ "Nom de la collection" ci-dessous ⬇️
Laisser un commentaire
emoji
💬 Ceci est un exemple de commentaire pour prévisualiser les styles.
0 sur 0 commentaires affichés
❌ Erreur de chargement
Signaler un commentaire
We got it.
Thank you for contacting us.
We’ll get back to you as soon as possible.









Partagez votre avis sur cet article ( 0 )