@reddoorla/maintenance 0.45.0 → 0.47.0
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/cli/bin.js +124 -42
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +90 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/bin.js
CHANGED
|
@@ -607,7 +607,10 @@ var init_checklist = __esm({
|
|
|
607
607
|
label: "Interactions & Animations",
|
|
608
608
|
field: "Test: Interactions & Animations"
|
|
609
609
|
},
|
|
610
|
-
|
|
610
|
+
// `field` keeps its original Airtable column name ("…Verified After Updates") even though
|
|
611
|
+
// the client-facing label is now "Tested After Updates" — the column holds operator data,
|
|
612
|
+
// so renaming the label is display-only and avoids a live-base column migration.
|
|
613
|
+
{ key: "updates", label: "Tested After Updates", field: "Test: Verified After Updates" }
|
|
611
614
|
];
|
|
612
615
|
ALL_CHECKLIST_FIELDS = [...MAINTENANCE_CHECKLIST, ...TESTING_CHECKLIST].map(
|
|
613
616
|
(i) => i.field
|
|
@@ -701,7 +704,7 @@ async function createDraft(base, input) {
|
|
|
701
704
|
async function setDraftReady(base, recordId, ready) {
|
|
702
705
|
await base(REPORTS_TABLE).update([{ id: recordId, fields: { "Draft ready": ready } }]);
|
|
703
706
|
}
|
|
704
|
-
async function updateReportScores(base, recordId, scores, completedOn) {
|
|
707
|
+
async function updateReportScores(base, recordId, scores, completedOn, enrichment) {
|
|
705
708
|
const fields = {
|
|
706
709
|
"Lighthouse \u2014 Performance": scores.performance,
|
|
707
710
|
"Lighthouse \u2014 Accessibility": scores.accessibility,
|
|
@@ -709,6 +712,14 @@ async function updateReportScores(base, recordId, scores, completedOn) {
|
|
|
709
712
|
"Lighthouse \u2014 SEO": scores.seo
|
|
710
713
|
};
|
|
711
714
|
if (completedOn) fields["Completed on"] = ymd(completedOn);
|
|
715
|
+
if (enrichment?.gaUsersCurrent !== void 0)
|
|
716
|
+
fields["GA users (period)"] = enrichment.gaUsersCurrent;
|
|
717
|
+
if (enrichment?.gaUsersPrevious !== void 0)
|
|
718
|
+
fields["GA users (prev period)"] = enrichment.gaUsersPrevious;
|
|
719
|
+
if (enrichment?.searchFoundPage1 !== void 0)
|
|
720
|
+
fields["Search found page 1"] = enrichment.searchFoundPage1;
|
|
721
|
+
if (enrichment?.searchPosition !== void 0)
|
|
722
|
+
fields["Search position"] = enrichment.searchPosition;
|
|
712
723
|
await base(REPORTS_TABLE).update([{ id: recordId, fields }]);
|
|
713
724
|
}
|
|
714
725
|
async function listSendableReports(base) {
|
|
@@ -808,7 +819,7 @@ var init_copy = __esm({
|
|
|
808
819
|
"Links & Navigation",
|
|
809
820
|
"Form Functionality",
|
|
810
821
|
"Interactions & Animations",
|
|
811
|
-
"
|
|
822
|
+
"Tested After Updates"
|
|
812
823
|
],
|
|
813
824
|
notesHeader: "NOTES",
|
|
814
825
|
seoCta: "Contact us if you are interested in more in-depth data or have questions about SEO.",
|
|
@@ -827,8 +838,8 @@ var init_copy = __esm({
|
|
|
827
838
|
announceCadenceHeading: "WHAT TO EXPECT",
|
|
828
839
|
announceTestingLabel: "Full site testing",
|
|
829
840
|
announceMaintenanceLabel: "Routine maintenance",
|
|
830
|
-
announceMonitorItems: ["Performance", "Accessibility", "Security", "Uptime"],
|
|
831
841
|
announcePreviewLabel: "From your latest full site test:",
|
|
842
|
+
announceScoreNote: "These are independent Google Lighthouse scores, each out of 100 \u2014 higher is better.",
|
|
832
843
|
announceImprovementResend: "Your contact forms now deliver straight to your inbox through reliable infrastructure, so no inquiry slips through the cracks.",
|
|
833
844
|
announceImprovementSvelte5: "We've modernized your site to the latest framework \u2014 it's faster, more secure, and built to last.",
|
|
834
845
|
announceCadence: "After each one we'll send you a short report like this \u2014 there's nothing you need to do.",
|
|
@@ -1049,7 +1060,7 @@ function buildMjml(data) {
|
|
|
1049
1060
|
<mj-text color="#C00" font-size="44px" font-weight="400" padding-top="0px">${data.lighthouse.performance}</mj-text>
|
|
1050
1061
|
<mj-text color="#757575" font-family="helvetica, sans-serif" font-size="12px" font-weight="300" padding-top="0px" padding-bottom="36px">Acceptable 50\u201389 // Ideal 90\u2013100</mj-text>
|
|
1051
1062
|
<mj-divider border-width="1px" border-style="solid" border-color="#CCCCCC" padding="0" />
|
|
1052
|
-
<mj-text color="#C00" font-size="20px" font-weight="300" padding-top="25px">Readability</mj-text>
|
|
1063
|
+
<mj-text color="#C00" font-size="20px" font-weight="300" padding-top="25px">Readability (A11y)</mj-text>
|
|
1053
1064
|
<mj-text color="#C00" font-size="44px" font-weight="400" padding-top="0px">${data.lighthouse.accessibility}</mj-text>
|
|
1054
1065
|
<mj-text color="#757575" font-family="helvetica, sans-serif" font-size="12px" font-weight="300" padding-top="0px" padding-bottom="36px">Acceptable 80\u201399 // Ideal 100</mj-text>
|
|
1055
1066
|
<mj-divider border-width="1px" border-style="solid" border-color="#CCCCCC" padding="0" />
|
|
@@ -1170,6 +1181,22 @@ var init_template2 = __esm({
|
|
|
1170
1181
|
});
|
|
1171
1182
|
|
|
1172
1183
|
// src/reports/announcement-email/template.ts
|
|
1184
|
+
function fmtVisitors(n) {
|
|
1185
|
+
return n.toLocaleString("en-US");
|
|
1186
|
+
}
|
|
1187
|
+
function visitorTrend(cur, prev) {
|
|
1188
|
+
if (cur === void 0 || prev === void 0 || prev === 0) return null;
|
|
1189
|
+
const pct = Math.round((cur - prev) / prev * 100);
|
|
1190
|
+
if (pct > 0) return `\u25B2 ${pct}% vs the previous month`;
|
|
1191
|
+
if (pct < 0) return `\u25BC ${Math.abs(pct)}% vs the previous month`;
|
|
1192
|
+
return "No change vs the previous month";
|
|
1193
|
+
}
|
|
1194
|
+
function announcementSiteExtras(site) {
|
|
1195
|
+
return {
|
|
1196
|
+
cadence: { maintenance: site.maintenanceFreq, testing: site.testingFreq },
|
|
1197
|
+
improvements: { resendForms: true, svelte5: true }
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1173
1200
|
function buildAnnouncementMjml(data) {
|
|
1174
1201
|
const copy = data.copy ?? DEFAULT_COPY;
|
|
1175
1202
|
const previewText = "Your monthly report from Reddoor";
|
|
@@ -1187,31 +1214,53 @@ function buildAnnouncementMjml(data) {
|
|
|
1187
1214
|
</mj-column>
|
|
1188
1215
|
</mj-section>` : "";
|
|
1189
1216
|
const cad = data.cadence;
|
|
1190
|
-
const
|
|
1217
|
+
const cadenceBlocks = [];
|
|
1191
1218
|
if (cad && cad.testing !== "None")
|
|
1192
|
-
|
|
1219
|
+
cadenceBlocks.push({
|
|
1220
|
+
line: `${copy.announceTestingLabel} \u2014 ${FREQ_PHRASE[cad.testing]}`,
|
|
1221
|
+
checks: copy.testingChecklist
|
|
1222
|
+
});
|
|
1193
1223
|
if (cad && cad.maintenance !== "None")
|
|
1194
|
-
|
|
1195
|
-
|
|
1224
|
+
cadenceBlocks.push({
|
|
1225
|
+
line: `${copy.announceMaintenanceLabel} \u2014 ${FREQ_PHRASE[cad.maintenance]}`,
|
|
1226
|
+
checks: copy.maintenanceChecks
|
|
1227
|
+
});
|
|
1228
|
+
const cadenceSection = cadenceBlocks.length > 0 ? `
|
|
1196
1229
|
<mj-section background-color="white">
|
|
1197
1230
|
<mj-column>
|
|
1198
1231
|
<mj-text color="${RED2}" font-size="20px" font-weight="700" padding-top="36px">${escapeXml(copy.announceCadenceHeading)}</mj-text>
|
|
1199
|
-
${
|
|
1200
|
-
(
|
|
1201
|
-
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="
|
|
1232
|
+
${cadenceBlocks.map(
|
|
1233
|
+
(b) => `
|
|
1234
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="400" line-height="24px" padding-top="12px" padding-bottom="2px">\u2022 ${escapeXml(b.line)}</mj-text>${b.checks.map(
|
|
1235
|
+
(c) => `
|
|
1236
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="14px" font-weight="300" line-height="22px" padding-top="1px" padding-bottom="0px" padding-left="16px">${escapeXml(c)} <img src="${CHECK_PNG2}" alt="\u2713" width="14" height="14" style="vertical-align:middle;display:inline-block;margin-left:2px;" /></mj-text>`
|
|
1237
|
+
).join("")}`
|
|
1202
1238
|
).join("")}
|
|
1203
|
-
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="
|
|
1239
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="14px">${escapeXml(copy.announceCadence)}</mj-text>
|
|
1204
1240
|
</mj-column>
|
|
1205
1241
|
</mj-section>` : "";
|
|
1206
|
-
const monitorRows = copy.announceMonitorItems.map(
|
|
1207
|
-
(item) => `
|
|
1208
|
-
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="4px" padding-bottom="4px">\u2022 ${escapeXml(item)}</mj-text>`
|
|
1209
|
-
).join("");
|
|
1210
1242
|
const scoreRows = SCORE_PREVIEW.map(
|
|
1211
1243
|
({ label, key }) => `
|
|
1212
1244
|
<mj-text color="${RED2}" font-size="20px" font-weight="300" padding-top="25px">${label}</mj-text>
|
|
1213
1245
|
<mj-text color="${RED2}" font-size="44px" font-weight="400" padding-top="0px">${data.lighthouse[key]}</mj-text>`
|
|
1214
1246
|
).join("");
|
|
1247
|
+
const scoreNote = copy.announceScoreNote ? `
|
|
1248
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="12px" font-weight="300" font-style="italic" line-height="18px" padding-top="16px">${escapeXml(copy.announceScoreNote)}</mj-text>` : "";
|
|
1249
|
+
const trend = visitorTrend(data.gaUsersCurrent, data.gaUsersPrevious);
|
|
1250
|
+
const trafficRows = [];
|
|
1251
|
+
if (data.gaUsersCurrent !== void 0)
|
|
1252
|
+
trafficRows.push(`
|
|
1253
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="8px"><span style="color:${RED2};font-size:22px;font-weight:400;">${escapeXml(fmtVisitors(data.gaUsersCurrent))}</span> visitors in the last month${trend ? ` \u2014 ${escapeXml(trend)}` : ""}</mj-text>`);
|
|
1254
|
+
if (data.searchPosition !== void 0)
|
|
1255
|
+
trafficRows.push(`
|
|
1256
|
+
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="4px">Page 1 Google result (#${data.searchPosition}) for your brand search</mj-text>`);
|
|
1257
|
+
const trafficSection = trafficRows.length > 0 ? `
|
|
1258
|
+
<mj-section background-color="white">
|
|
1259
|
+
<mj-column>
|
|
1260
|
+
<mj-text color="${RED2}" font-size="20px" font-weight="700" padding-top="36px">TRAFFIC & SEARCH</mj-text>
|
|
1261
|
+
${trafficRows.join("")}
|
|
1262
|
+
</mj-column>
|
|
1263
|
+
</mj-section>` : "";
|
|
1215
1264
|
const contactRows = copy.contact.map(
|
|
1216
1265
|
(line) => `
|
|
1217
1266
|
<mj-text font-family="helvetica, sans-serif" font-size="24px" font-weight="300" line-height="30px">${escapeXml(line)}</mj-text>`
|
|
@@ -1243,18 +1292,13 @@ function buildAnnouncementMjml(data) {
|
|
|
1243
1292
|
</mj-section>
|
|
1244
1293
|
${cadenceSection}
|
|
1245
1294
|
${improvementsSection}
|
|
1246
|
-
<mj-section background-color="white">
|
|
1247
|
-
<mj-column>
|
|
1248
|
-
<mj-text color="${RED2}" font-size="20px" font-weight="700" padding-top="36px">WHAT WE MONITOR</mj-text>
|
|
1249
|
-
${monitorRows}
|
|
1250
|
-
</mj-column>
|
|
1251
|
-
</mj-section>
|
|
1252
1295
|
<mj-section background-color="#F4F4F4">
|
|
1253
1296
|
<mj-column>
|
|
1254
1297
|
<mj-text color="${RED2}" font-size="20px" font-weight="700" padding-top="55px">${escapeXml(copy.announcePreviewLabel)}</mj-text>
|
|
1255
|
-
${scoreRows}
|
|
1298
|
+
${scoreRows}${scoreNote}
|
|
1256
1299
|
</mj-column>
|
|
1257
1300
|
</mj-section>
|
|
1301
|
+
${trafficSection}
|
|
1258
1302
|
<mj-section background-color="white">
|
|
1259
1303
|
<mj-column>
|
|
1260
1304
|
<mj-text color="${GREY2}" font-family="helvetica, sans-serif" font-size="16px" font-weight="300" line-height="24px" padding-top="36px">${escapeXml(copy.announceOpenDoor)}</mj-text>
|
|
@@ -1274,12 +1318,13 @@ function buildAnnouncementMjml(data) {
|
|
|
1274
1318
|
</mj-body>
|
|
1275
1319
|
</mjml>`;
|
|
1276
1320
|
}
|
|
1277
|
-
var FREQ_PHRASE, RED2, GREY2, SCORE_PREVIEW;
|
|
1321
|
+
var FREQ_PHRASE, RED2, GREY2, CHECK_PNG2, SCORE_PREVIEW;
|
|
1278
1322
|
var init_template3 = __esm({
|
|
1279
1323
|
"src/reports/announcement-email/template.ts"() {
|
|
1280
1324
|
"use strict";
|
|
1281
1325
|
init_copy();
|
|
1282
1326
|
init_template();
|
|
1327
|
+
init_assets();
|
|
1283
1328
|
FREQ_PHRASE = {
|
|
1284
1329
|
Monthly: "every month",
|
|
1285
1330
|
Quarterly: "every quarter",
|
|
@@ -1287,9 +1332,10 @@ var init_template3 = __esm({
|
|
|
1287
1332
|
};
|
|
1288
1333
|
RED2 = "#C00";
|
|
1289
1334
|
GREY2 = "#757575";
|
|
1335
|
+
CHECK_PNG2 = `cid:${CHECK_CID}`;
|
|
1290
1336
|
SCORE_PREVIEW = [
|
|
1291
1337
|
{ label: "Performance", key: "performance" },
|
|
1292
|
-
{ label: "Readability", key: "accessibility" },
|
|
1338
|
+
{ label: "Readability (A11y)", key: "accessibility" },
|
|
1293
1339
|
{ label: "Best Practices", key: "bestPractices" },
|
|
1294
1340
|
{ label: "Site Structure", key: "seo" }
|
|
1295
1341
|
];
|
|
@@ -1955,7 +2001,12 @@ async function sendOne(client, base, site, report) {
|
|
|
1955
2001
|
headerImageCid: cidName,
|
|
1956
2002
|
headerWidth: header.displayWidth,
|
|
1957
2003
|
headerHeight: header.displayHeight,
|
|
1958
|
-
headerBgColor: header.placeholderColor
|
|
2004
|
+
headerBgColor: header.placeholderColor,
|
|
2005
|
+
// Announcement-only: re-derive cadence + improvements from the site row so the SENT email
|
|
2006
|
+
// keeps its WHAT TO EXPECT section + improvement callouts. Without this the send-time
|
|
2007
|
+
// re-render drops them entirely (they're not stored on the Reports row). Ignored by the
|
|
2008
|
+
// other report templates.
|
|
2009
|
+
...report.reportType === "Announcement" ? announcementSiteExtras(site) : {}
|
|
1959
2010
|
});
|
|
1960
2011
|
const reportDate = report.completedOn ? new Date(report.completedOn) : /* @__PURE__ */ new Date();
|
|
1961
2012
|
const subject = report.subjectOverride ?? `${site.name} \u2014 ${monthYear(reportDate)} ${report.reportType} Report`;
|
|
@@ -2041,6 +2092,7 @@ var init_orchestrate = __esm({
|
|
|
2041
2092
|
init_attachments();
|
|
2042
2093
|
init_render();
|
|
2043
2094
|
init_copy();
|
|
2095
|
+
init_template3();
|
|
2044
2096
|
init_assets();
|
|
2045
2097
|
init_header_image();
|
|
2046
2098
|
init_resend();
|
|
@@ -5780,6 +5832,7 @@ import { JWT as JWT2 } from "google-auth-library";
|
|
|
5780
5832
|
var WEBMASTERS_READONLY = "https://www.googleapis.com/auth/webmasters.readonly";
|
|
5781
5833
|
var SC_BASE = "https://searchconsole.googleapis.com/webmasters/v3";
|
|
5782
5834
|
var PAGE_1_MAX_POSITION = 10;
|
|
5835
|
+
var BRAND_QUERY_ROW_LIMIT = 100;
|
|
5783
5836
|
function bareHost(s) {
|
|
5784
5837
|
return s.trim().replace(/^sc-domain:/i, "").replace(/^https?:\/\//i, "").split("/")[0].replace(/^www\./i, "").toLowerCase();
|
|
5785
5838
|
}
|
|
@@ -5793,6 +5846,25 @@ function resolvePropertyCandidates(entries, host) {
|
|
|
5793
5846
|
function ymd3(d) {
|
|
5794
5847
|
return d.toISOString().slice(0, 10);
|
|
5795
5848
|
}
|
|
5849
|
+
function pickBrandQuery(rows) {
|
|
5850
|
+
let best;
|
|
5851
|
+
for (const r of rows) {
|
|
5852
|
+
if (typeof r.position !== "number") continue;
|
|
5853
|
+
const impressions = r.impressions ?? 0;
|
|
5854
|
+
if (best === void 0 || impressions > best.impressions || impressions === best.impressions && r.position < best.position) {
|
|
5855
|
+
best = { position: r.position, impressions };
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
return best?.position;
|
|
5859
|
+
}
|
|
5860
|
+
function selectBrandPosition(rows, exactQuery) {
|
|
5861
|
+
const want = exactQuery.toLowerCase();
|
|
5862
|
+
const exact = rows.find(
|
|
5863
|
+
(r) => typeof r.position === "number" && (r.keys?.[0] ?? "").toLowerCase() === want
|
|
5864
|
+
);
|
|
5865
|
+
if (exact) return exact.position;
|
|
5866
|
+
return pickBrandQuery(rows);
|
|
5867
|
+
}
|
|
5796
5868
|
async function fetchSearchPresence(q, periodStart, periodEnd) {
|
|
5797
5869
|
const key = JSON.parse(readFileSync4(q.keyPath, "utf8"));
|
|
5798
5870
|
const jwt = new JWT2({
|
|
@@ -5824,14 +5896,14 @@ async function fetchSearchPresence(q, periodStart, periodEnd) {
|
|
|
5824
5896
|
dimensionFilterGroups: [
|
|
5825
5897
|
{
|
|
5826
5898
|
filters: [
|
|
5827
|
-
{ dimension: "query", operator: "
|
|
5899
|
+
{ dimension: "query", operator: "contains", expression: q.query.toLowerCase() }
|
|
5828
5900
|
]
|
|
5829
5901
|
}
|
|
5830
5902
|
],
|
|
5831
|
-
rowLimit:
|
|
5903
|
+
rowLimit: BRAND_QUERY_ROW_LIMIT
|
|
5832
5904
|
}
|
|
5833
5905
|
});
|
|
5834
|
-
const pos = res.data.rows
|
|
5906
|
+
const pos = selectBrandPosition(res.data.rows ?? [], q.query.toLowerCase());
|
|
5835
5907
|
if (typeof pos === "number") {
|
|
5836
5908
|
return { foundOnPage1: pos <= PAGE_1_MAX_POSITION, position: Math.max(1, Math.round(pos)) };
|
|
5837
5909
|
}
|
|
@@ -6423,6 +6495,7 @@ init_reports();
|
|
|
6423
6495
|
init_attachments();
|
|
6424
6496
|
init_render();
|
|
6425
6497
|
init_copy();
|
|
6498
|
+
init_template3();
|
|
6426
6499
|
async function announce(deps) {
|
|
6427
6500
|
const base = deps?.base ?? openBase(readAirtableConfig());
|
|
6428
6501
|
const now = deps?.now ?? /* @__PURE__ */ new Date();
|
|
@@ -6441,15 +6514,24 @@ async function announce(deps) {
|
|
|
6441
6514
|
results.push({ site: w.name, status: "skipped-no-scores" });
|
|
6442
6515
|
continue;
|
|
6443
6516
|
}
|
|
6517
|
+
const periodEnd = now;
|
|
6518
|
+
const periodStart = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1e3);
|
|
6519
|
+
const gaUsers = (await fetchGaUsers(w, periodStart, periodEnd)).value;
|
|
6520
|
+
const search = (await fetchSearch(w, periodStart, periodEnd)).value;
|
|
6521
|
+
const enrichment = {
|
|
6522
|
+
...gaUsers ? { gaUsersCurrent: gaUsers.current, gaUsersPrevious: gaUsers.previous } : {},
|
|
6523
|
+
...search ? { searchFoundPage1: search.foundOnPage1 } : {},
|
|
6524
|
+
...search?.foundOnPage1 && search.position !== null ? { searchPosition: search.position } : {}
|
|
6525
|
+
};
|
|
6444
6526
|
let report;
|
|
6445
6527
|
let statusKind;
|
|
6446
6528
|
const existing = await findReportByPeriod(base, w.id, "Announcement", period);
|
|
6447
6529
|
if (existing) {
|
|
6448
|
-
await updateReportScores(base, existing.id, scores, now);
|
|
6530
|
+
await updateReportScores(base, existing.id, scores, now, enrichment);
|
|
6449
6531
|
report = existing;
|
|
6450
6532
|
statusKind = "reused";
|
|
6451
6533
|
} else {
|
|
6452
|
-
report = await createDraft(base, draftInputFor2(w, scores, now, period));
|
|
6534
|
+
report = await createDraft(base, draftInputFor2(w, scores, now, period, enrichment));
|
|
6453
6535
|
statusKind = "drafted";
|
|
6454
6536
|
}
|
|
6455
6537
|
const slug = siteSlug(w.name);
|
|
@@ -6459,18 +6541,17 @@ async function announce(deps) {
|
|
|
6459
6541
|
reportType: "Announcement",
|
|
6460
6542
|
completedOn: now,
|
|
6461
6543
|
lighthouse: scores,
|
|
6544
|
+
gaUsersCurrent: gaUsers?.current,
|
|
6545
|
+
gaUsersPrevious: gaUsers?.previous,
|
|
6546
|
+
searchPosition: search?.foundOnPage1 ? search.position ?? void 0 : void 0,
|
|
6462
6547
|
lastTestedDate: null,
|
|
6463
6548
|
commentary: null,
|
|
6464
6549
|
copy: resolveCopy(w),
|
|
6465
6550
|
headerImageCid: `${slug}-header`,
|
|
6466
|
-
//
|
|
6467
|
-
//
|
|
6468
|
-
//
|
|
6469
|
-
|
|
6470
|
-
// Default-on fleet-wide for v1: both recent-improvement callouts render for every
|
|
6471
|
-
// site. Operator review (the draft never auto-sends) is the relevance backstop;
|
|
6472
|
-
// per-site conditioning of these flags is a future lever, not a v1 requirement.
|
|
6473
|
-
improvements: { resendForms: true, svelte5: true }
|
|
6551
|
+
// cadence (the client's go-forward pace, "None" omitted) + default-on improvement
|
|
6552
|
+
// callouts. Shared with the send re-render via announcementSiteExtras so the sent
|
|
6553
|
+
// email matches this reviewed preview.
|
|
6554
|
+
...announcementSiteExtras(w)
|
|
6474
6555
|
});
|
|
6475
6556
|
try {
|
|
6476
6557
|
await uploadAttachment(
|
|
@@ -6509,7 +6590,7 @@ function scoresFromRow(w) {
|
|
|
6509
6590
|
seo: w.seoScore
|
|
6510
6591
|
};
|
|
6511
6592
|
}
|
|
6512
|
-
function draftInputFor2(w, scores, now, period) {
|
|
6593
|
+
function draftInputFor2(w, scores, now, period, enrichment) {
|
|
6513
6594
|
return {
|
|
6514
6595
|
reportId: `${w.name} \u2014 Announcement \u2014 ${now.toISOString().slice(0, 10)}`,
|
|
6515
6596
|
siteId: w.id,
|
|
@@ -6520,7 +6601,8 @@ function draftInputFor2(w, scores, now, period) {
|
|
|
6520
6601
|
completedOn: now,
|
|
6521
6602
|
lighthouse: scores,
|
|
6522
6603
|
lastTestedDate: null,
|
|
6523
|
-
subjectOverride: `Your testing & maintenance schedule for ${w.name}
|
|
6604
|
+
subjectOverride: `Your testing & maintenance schedule for ${w.name}`,
|
|
6605
|
+
...enrichment
|
|
6524
6606
|
};
|
|
6525
6607
|
}
|
|
6526
6608
|
|