feat: enhance analytics mailer with umami entry/exit pages and beginner-friendly UI
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧹 Lint (push) Failing after 1m23s
Monorepo Pipeline / 🧪 Test (push) Successful in 41s
Monorepo Pipeline / 🏗️ Build (push) Successful in 2m20s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
Analytics Mailer / 📊 Send Analytics Reports (push) Successful in 48s
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 7s
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧹 Lint (push) Failing after 1m23s
Monorepo Pipeline / 🧪 Test (push) Successful in 41s
Monorepo Pipeline / 🏗️ Build (push) Successful in 2m20s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
Analytics Mailer / 📊 Send Analytics Reports (push) Successful in 48s
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 7s
This commit is contained in:
41
packages/mail/src/templates/AnalyticsTemplate.test.tsx
Normal file
41
packages/mail/src/templates/AnalyticsTemplate.test.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { render } from "@react-email/components";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { AnalyticsTemplate, PeriodData } from "./AnalyticsTemplate";
|
||||
import * as React from "react";
|
||||
|
||||
describe("AnalyticsTemplate", () => {
|
||||
it("renders entry and exit pages correctly", async () => {
|
||||
const period: PeriodData = {
|
||||
label: "Test Period",
|
||||
visitors: 100,
|
||||
visits: 120,
|
||||
views: 500,
|
||||
bounceRate: 50,
|
||||
visitDuration: "2m",
|
||||
topPages: [{ url: "/home", views: 50 }],
|
||||
topReferrers: [{ url: "google.com", visitors: 30 }],
|
||||
// These fields will cause a TS error because they don't exist yet,
|
||||
// but we force it to see it fail.
|
||||
topEntryPages: [{ url: "/entry", visitors: 40 }],
|
||||
topExitPages: [{ url: "/exit", visitors: 20 }],
|
||||
chartData: [],
|
||||
} as any; // Cast as any to bypass TS compilation before we update the type
|
||||
|
||||
const html = await render(
|
||||
<AnalyticsTemplate
|
||||
greeting="Hallo Kunde,"
|
||||
domain="example.com"
|
||||
periods={[period]}
|
||||
/>
|
||||
);
|
||||
|
||||
// Assert that the new sections for entry and exit pages exist.
|
||||
expect(html).toContain("Häufigste Einstiege");
|
||||
expect(html).toContain("Häufigste Ausstiege");
|
||||
expect(html).toContain("/entry");
|
||||
expect(html).toContain("/exit");
|
||||
|
||||
// Assert that the badges have updated line heights
|
||||
expect(html).toContain('line-height:1.5');
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,8 @@ export interface PeriodData {
|
||||
visitDuration: string;
|
||||
topPages: { url: string; views: number }[];
|
||||
topReferrers: { url: string; visitors: number }[];
|
||||
topEntryPages: { url: string; visitors: number }[];
|
||||
topExitPages: { url: string; visitors: number }[];
|
||||
chartData: { label: string; value: number }[];
|
||||
}
|
||||
|
||||
@@ -135,8 +137,8 @@ export const AnalyticsTemplate = ({
|
||||
<tr>
|
||||
<td width="48%" valign="top">
|
||||
<div style={listContainer}>
|
||||
<Text style={listTitle}>Seiten</Text>
|
||||
<Text style={listSubtitle}>Die beliebtesten Unterseiten sortiert nach Aufrufen.</Text>
|
||||
<Text style={listTitle}>Beliebteste Seiten</Text>
|
||||
<Text style={listSubtitle}>Was schauen sich Ihre Besucher am häufigsten an?</Text>
|
||||
{period.topPages.map((p, idx) => (
|
||||
<Row key={idx} style={listRow}>
|
||||
<Column><Text style={listText}>{p.url}</Text></Column>
|
||||
@@ -148,8 +150,8 @@ export const AnalyticsTemplate = ({
|
||||
<td width="4%" />
|
||||
<td width="48%" valign="top">
|
||||
<div style={listContainer}>
|
||||
<Text style={listTitle}>Quellen</Text>
|
||||
<Text style={listSubtitle}>Woher Ihre Besucher auf die Website kommen.</Text>
|
||||
<Text style={listTitle}>Woher kommen Ihre Besucher?</Text>
|
||||
<Text style={listSubtitle}>Wie wurden Sie gefunden? (z.B. Google, Direkt)</Text>
|
||||
{period.topReferrers.map((r, idx) => (
|
||||
<Row key={idx} style={listRow}>
|
||||
<Column><Text style={listText}>{r.url || "Direktaufruf"}</Text></Column>
|
||||
@@ -161,6 +163,38 @@ export const AnalyticsTemplate = ({
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table width="100%" border={0} cellPadding="0" cellSpacing="0" style={tablesContainer}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="48%" valign="top">
|
||||
<div style={listContainer}>
|
||||
<Text style={listTitle}>Häufigste Einstiege</Text>
|
||||
<Text style={listSubtitle}>Auf welchen Seiten starten Ihre Besucher?</Text>
|
||||
{period.topEntryPages?.map((p, idx) => (
|
||||
<Row key={idx} style={listRow}>
|
||||
<Column><Text style={listText}>{p.url}</Text></Column>
|
||||
<Column align="right"><Text style={listTextBold}>{p.visitors.toLocaleString("de-DE")}</Text></Column>
|
||||
</Row>
|
||||
))}
|
||||
</div>
|
||||
</td>
|
||||
<td width="4%" />
|
||||
<td width="48%" valign="top">
|
||||
<div style={listContainer}>
|
||||
<Text style={listTitle}>Häufigste Ausstiege</Text>
|
||||
<Text style={listSubtitle}>Wo verlassen Besucher Ihre Website am häufigsten?</Text>
|
||||
{period.topExitPages?.map((p, idx) => (
|
||||
<Row key={idx} style={listRow}>
|
||||
<Column><Text style={listText}>{p.url}</Text></Column>
|
||||
<Column align="right"><Text style={listTextBold}>{p.visitors.toLocaleString("de-DE")}</Text></Column>
|
||||
</Row>
|
||||
))}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style={divider} />
|
||||
</Section>
|
||||
))}
|
||||
@@ -332,6 +366,7 @@ const badgePositive = {
|
||||
fontWeight: "bold",
|
||||
color: "#16a34a",
|
||||
margin: "4px 0 0 0",
|
||||
lineHeight: "1.5",
|
||||
};
|
||||
|
||||
const badgeNeutral = {
|
||||
@@ -339,4 +374,5 @@ const badgeNeutral = {
|
||||
fontWeight: "bold",
|
||||
color: "#6b7280",
|
||||
margin: "4px 0 0 0",
|
||||
lineHeight: "1.5",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user