doctrine 193: ux-audit-mobile-banner.js Playwright iPhone12 viewport audit script - detect bottom-right overlaps (bot widget vs injected banners) - 4 pages scanned / 1 overlap found leadforge.html - proofs public URL
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
This commit is contained in:
135
ops-scripts/ux-audit-mobile-banner.js
Normal file
135
ops-scripts/ux-audit-mobile-banner.js
Normal file
@@ -0,0 +1,135 @@
|
||||
// UX Audit Mobile Banner Overlap — doctrine Yacine "banner CTA chevauche Brain+WhatsApp bottom-right sur mobile"
|
||||
// Crée par Opus session v1.9 — cible pages publiques + mobile viewport
|
||||
const { chromium, devices } = require('playwright');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
(async () => {
|
||||
const out = '/var/www/html/proofs/ux-audit-mobile-banner-' + new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
||||
fs.mkdirSync(out, { recursive: true });
|
||||
const logFile = path.join(out, 'audit.log');
|
||||
const log = (m) => { console.log(m); fs.appendFileSync(logFile, m + '\n'); };
|
||||
fs.writeFileSync(logFile, '');
|
||||
|
||||
log('=== UX AUDIT MOBILE BANNER OVERLAP ===');
|
||||
log('started: ' + new Date().toISOString());
|
||||
|
||||
const b = await chromium.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
|
||||
// iPhone 12 viewport: 390x844
|
||||
const c = await b.newContext({
|
||||
...devices['iPhone 12'],
|
||||
recordVideo: { dir: out, size: { width: 390, height: 844 } }
|
||||
});
|
||||
const p = await c.newPage();
|
||||
|
||||
const pages = [
|
||||
{ url: 'https://weval-consulting.com/', name: 'landing-index', slug: 'index' },
|
||||
{ url: 'https://weval-consulting.com/products/consulting.html', name: 'products-consulting', slug: 'consulting' },
|
||||
{ url: 'https://weval-consulting.com/products/leadforge.html', name: 'products-leadforge', slug: 'leadforge' },
|
||||
{ url: 'https://weval-consulting.com/products/academy-elearning-v2.html', name: 'products-academy', slug: 'academy' }
|
||||
];
|
||||
|
||||
const report = { mobile_viewport: '390x844 iPhone12', pages: [], total_overlaps: 0, cta_detected: 0 };
|
||||
|
||||
for (const target of pages) {
|
||||
log(`--- scanning ${target.name} (${target.url}) ---`);
|
||||
const pageReport = { name: target.name, url: target.url, overlaps: [], cta_text: null, bottom_right_elements: 0 };
|
||||
try {
|
||||
await p.goto(target.url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
||||
await p.waitForTimeout(3500); // let widget/brain/whatsapp inject
|
||||
|
||||
// Full page screenshot
|
||||
await p.screenshot({ path: path.join(out, `${target.slug}-full.png`), fullPage: false });
|
||||
|
||||
// Zoom bottom-right (viewport 0 - last 250px h, last 200px w)
|
||||
await p.screenshot({
|
||||
path: path.join(out, `${target.slug}-bottomright-zoom.png`),
|
||||
clip: { x: 390 - 200, y: 844 - 250, width: 200, height: 250 }
|
||||
});
|
||||
|
||||
// Detect all fixed/sticky positioned elements
|
||||
const fixedEls = await p.evaluate(() => {
|
||||
const all = document.querySelectorAll('*');
|
||||
const fixed = [];
|
||||
for (const el of all) {
|
||||
const s = getComputedStyle(el);
|
||||
if ((s.position === 'fixed' || s.position === 'sticky') && s.display !== 'none' && s.visibility !== 'hidden' && parseFloat(s.opacity) > 0.1) {
|
||||
const r = el.getBoundingClientRect();
|
||||
if (r.width > 0 && r.height > 0 && r.width < 500 && r.height < 500) {
|
||||
fixed.push({
|
||||
tag: el.tagName,
|
||||
id: el.id || '',
|
||||
cls: (el.className || '').toString().slice(0, 100),
|
||||
pos: {
|
||||
top: Math.round(r.top),
|
||||
left: Math.round(r.left),
|
||||
right: Math.round(window.innerWidth - r.right),
|
||||
bottom: Math.round(window.innerHeight - r.bottom),
|
||||
w: Math.round(r.width),
|
||||
h: Math.round(r.height)
|
||||
},
|
||||
zIndex: s.zIndex,
|
||||
text: (el.textContent || '').trim().slice(0, 60)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return fixed;
|
||||
});
|
||||
|
||||
log(` fixed/sticky: ${fixedEls.length}`);
|
||||
|
||||
// Find CTA text ("Demander un devis", "Prendre RDV", "Devis")
|
||||
const ctaEls = fixedEls.filter(e =>
|
||||
/demander.*devis|prendre.*rdv|contact|devis|rdv/i.test(e.text)
|
||||
);
|
||||
if (ctaEls.length > 0) {
|
||||
pageReport.cta_text = ctaEls[0].text;
|
||||
report.cta_detected++;
|
||||
log(` CTA found: "${ctaEls[0].text}" at pos ${JSON.stringify(ctaEls[0].pos)}`);
|
||||
}
|
||||
|
||||
// Bottom-right zone: right < 80, bottom < 200
|
||||
const br = fixedEls.filter(e => e.pos.right < 80 && e.pos.bottom < 200);
|
||||
pageReport.bottom_right_elements = br.length;
|
||||
log(` bottom-right elements: ${br.length}`);
|
||||
for (const e of br) log(` - ${e.tag}#${e.id}.${e.cls.slice(0,40)} pos=${JSON.stringify(e.pos)} text="${e.text}"`);
|
||||
|
||||
// Detect overlaps in bottom-right
|
||||
for (let i = 0; i < br.length; i++) {
|
||||
for (let j = i + 1; j < br.length; j++) {
|
||||
const a = br[i].pos, b = br[j].pos;
|
||||
const aL = a.left, aR = a.left + a.w, aT = a.top, aB = a.top + a.h;
|
||||
const bL = b.left, bR = b.left + b.w, bT = b.top, bB = b.top + b.h;
|
||||
if (aL < bR && aR > bL && aT < bB && aB > bT) {
|
||||
const overlap = {
|
||||
zone: 'bottom-right',
|
||||
elemA: { tag: br[i].tag, id: br[i].id, text: br[i].text, pos: a },
|
||||
elemB: { tag: br[j].tag, id: br[j].id, text: br[j].text, pos: b }
|
||||
};
|
||||
pageReport.overlaps.push(overlap);
|
||||
report.total_overlaps++;
|
||||
log(` 🔴 OVERLAP detected: [${br[i].id || br[i].tag}] <-> [${br[j].id || br[j].tag}]`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pageReport.all_fixed_els = fixedEls;
|
||||
} catch (e) {
|
||||
log(` ERROR: ${e.message}`);
|
||||
pageReport.error = e.message;
|
||||
}
|
||||
report.pages.push(pageReport);
|
||||
}
|
||||
|
||||
// Save JSON report
|
||||
fs.writeFileSync(path.join(out, 'report.json'), JSON.stringify(report, null, 2));
|
||||
log('=== SUMMARY ===');
|
||||
log(`total_overlaps: ${report.total_overlaps}`);
|
||||
log(`cta_detected: ${report.cta_detected}`);
|
||||
log(`output: ${out}`);
|
||||
log(`public URL: https://weval-consulting.com/proofs/${path.basename(out)}/`);
|
||||
|
||||
await c.close();
|
||||
await b.close();
|
||||
})().catch(e => { console.error('FATAL:', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user