Le Carnet : vos crédits de services évoluent
Chez FolioDesign, les Crédits de Services existent déjà dans votre offre pour vous permettre de profiter de certains ajustements, services et évolutions sans frais complémentaires sur les prestations éligibles. Aujourd'hui, ce fonctionnement évolue avec un espace plus clair, plus simple à utiliser et plus transparent : le Carnet .
Le Carnet a été pensé pour vous offrir une meilleure visibilité sur vos crédits de services et sur leur utilisation au fil du temps. En quelques instants, vous pouvez consulter votre solde, suivre vos transactions et retrouver les services liés à votre offre dans un seul espace dédié.
Un espace plus clair pour suivre vos crédits
Le Carnet centralise les informations essentielles liées à vos crédits de services. Vous y retrouvez votre solde disponible , les crédits ajoutés , les débits effectués ainsi que l'historique des opérations liées à vos services.
Cette nouvelle présentation rend la gestion de vos crédit plus lisible au quotidien. Vous savez plus facilement où vous en êtes, ce qui a été crédité, ce qui a été utilisé, et comment votre solde évolue dans le temps.
Le Carnet a été conçu pour rendre l'expérience plus simple, sans complexifier votre relation avec vos services. L'objectif est de vous permettre de profiter plus facilement de ce qui est déjà inclus dans votre offre.
Des crédits ajoutés chaque mois selon votre offre
Votre Carnet est alimenté automatiquement en crédit chaque mois selon le forfait souscrit. Chaque client bénéficie ainsi d'un rythme de crédit adapté à son offre, avec une logique simple et régulière.
Les crédits s'accumulent dans votre Carnet dans la limite prévue par votre formule. Vous disposez donc d'une réserve claire pour vos besoins futurs, avec une vision plus précise de votre capacité d'utilisation sur les services éligibles.
Une utilisation plus fluide sur les services éligibles
Grâce au Carnet, vous pouvez utiliser plus facilement vos crédits sur certains services proposés par FolioDesign et sur les éléments éligibles de votre univers FolioMarket. Selon votre offre, cela peut concerner des ajustements, des options, certains services ou applications.
Chaque utilisation est enregistrée de façon claire, avec un suivi plus simple des opérations et des statuts. Vous bénéficiez ainsi d'une expérience plus fluide, avec un lien direct entre votre offre, vos crédits et vos services.
Vous êtes également informé des opérations importantes liées à votre Carnet, comme l'ajout de crédits, les débits liés à un service, l'état d'un abonnement ou certaines évolutions de vos opérations. Tout est pensé pour rendre le suivi plus transparent.
Une évolution utile au quotidien
Le Carnet fait évoluer le fonctionnement de vos crédits de services pour vous offrir une expérience plus claire, plus pratique et plus utile au quotidien. Vous gardez ainsi une meilleure maîtrise de vos crédit, de vos services et de l'évolution de votre solde.
Avec FolioDesign, vos crédits de services restent intégrés à votre offre, sont ajoutés chaque mois selon votre forfait et deviennent plus simples à consulter, à comprendre et à utiliser dans le temps.
En résumé
Le Carnet vous permet de suivre plus facilement vos crédits, vos transactions et vos services éligibles dans un seul espace. C'est une évolution naturelle de vos crédits de services, pensée pour vous offrir plus de clarté, plus de souplesse et une meilleure expérience dans la durée.
Retrouvez votre Carnet sur FolioMarket et profitez d'un espace plus simple pour suivre et utiliser vos crédits de services.
🚀 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 )