File: //proc/self/root/tmp/dateweb_patch_query_insights.cjs
const fs = require('fs');
const file = 'scripts/growth-insights.mjs';
let s = fs.readFileSync(file, 'utf8');
if (!s.includes('function queryParams(path)')) {
s = s.replace(`function sameSiteReferrerPath(referrer) {`, `function queryParams(path) {
const raw = path || '/';
const queryIndex = raw.indexOf('?');
if (queryIndex === -1) return new URLSearchParams();
try {
return new URLSearchParams(raw.slice(queryIndex + 1));
} catch {
return new URLSearchParams();
}
}
function sameSiteReferrerPath(referrer) {`);
}
if (!s.includes('const fromParamCounts = new Map();')) {
s = s.replace(`const ipCounts = new Map();`, `const ipCounts = new Map();
const fromParamCounts = new Map();
const mtmCampaignCounts = new Map();
const mtmSourceCounts = new Map();
const mtmKeywordCounts = new Map();
const campaignTargetCounts = new Map();`);
}
if (!s.includes('const params = queryParams(row.path);')) {
s = s.replace(`for (const row of humanish) {
const path = normalizePath(row.path);`, `for (const row of humanish) {
const path = normalizePath(row.path);
const params = queryParams(row.path);
const from = params.get('from');
const mtmCampaign = params.get('mtm_campaign');
const mtmSource = params.get('mtm_source');
const mtmKeyword = params.get('mtm_keyword');
if (from) inc(fromParamCounts, from.slice(0, 90));
if (mtmCampaign) inc(mtmCampaignCounts, mtmCampaign.slice(0, 90));
if (mtmSource) inc(mtmSourceCounts, mtmSource.slice(0, 60));
if (mtmKeyword) inc(mtmKeywordCounts, mtmKeyword.slice(0, 90));
if (from || mtmCampaign) inc(campaignTargetCounts, path);`);
}
if (!s.includes('const topFromParams = topEntries(fromParamCounts')) {
s = s.replace(`const topIp = topEntries(ipCounts, 10).map(([ip, count]) => [ip, String(count)]);`, `const topIp = topEntries(ipCounts, 10).map(([ip, count]) => [ip, String(count)]);
const topFromParams = topEntries(fromParamCounts, 15).map(([value, count]) => [value, String(count)]);
const topMtmCampaigns = topEntries(mtmCampaignCounts, 15).map(([value, count]) => [value, String(count)]);
const topMtmSources = topEntries(mtmSourceCounts, 10).map(([value, count]) => [value, String(count)]);
const topMtmKeywords = topEntries(mtmKeywordCounts, 15).map(([value, count]) => [value, String(count)]);
const topCampaignTargets = topEntries(campaignTargetCounts, 15).map(([path, count]) => [\`\${path}\`, String(count)]);`);
}
if (!s.includes('Bridge- und Kampagnen-Signale')) {
s = s.replace(`## Top Register-Referrer auf dateweb.de
\${table(topRegisterReferrers, ['Referrer-Pfad', 'Requests'])}
## Seitentypen im Logfenster`, `## Top Register-Referrer auf dateweb.de
\${table(topRegisterReferrers, ['Referrer-Pfad', 'Requests'])}
## Bridge- und Kampagnen-Signale
### Interne from-Parameter
\${table(topFromParams, ['from', 'Requests'])}
### Matomo-Kampagnen
\${table(topMtmCampaigns, ['mtm_campaign', 'Requests'])}
### Matomo-Quellen
\${table(topMtmSources, ['mtm_source', 'Requests'])}
### Matomo-Keywords
\${table(topMtmKeywords, ['mtm_keyword', 'Requests'])}
### Kampagnen-Zielpfade
\${table(topCampaignTargets, ['Pfad', 'Requests'])}
## Seitentypen im Logfenster`);
}
if (!s.includes('Bridge-/Kampagnenparameter sind sichtbar')) {
s = s.replace(`recommendations.push('Search Console und Matomo bleiben die Primärquellen für Ranking, Impressionen und Conversion; diese Serverlog-Auswertung ergänzt sie als unabhängiger Reality-Check.');`, `if (fromParamCounts.size > 0 || mtmCampaignCounts.size > 0) {
recommendations.push('Bridge-/Kampagnenparameter sind sichtbar. Erfolgreiche from- und mtm-Muster in CTAs priorisieren und schwache Muster nach 48-72 Stunden entfernen.');
}
recommendations.push('Search Console und Matomo bleiben die Primärquellen für Ranking, Impressionen und Conversion; diese Serverlog-Auswertung ergänzt sie als unabhängiger Reality-Check.');`);
}
fs.writeFileSync(file, s, 'utf8');