feat(home): prova no topo, contato sem atrito e conversão medida
Home mais curta (hero, vitrine de clientes, sobre, serviços, IA resumida, depoimentos e contato), faixa de clientes e telas reais no hero, sem números do GitHub. Barra de cookies fina, WhatsApp fixo no celular, formulário com e-mail opcional e alternativa por e-mail, página /ia, eventos de e-mail, redes e currículo e conversão do Ads opcional por variável. Rodapé em 3 colunas. Remove componentes órfãos (LighthouseMetrics, Skills, Experience, contagem do GitHub).
This commit is contained in:
1 parent
6e1022b58c
commit
8d07b8c6bb
60 files changed
+4392
-2124
No files matched your search
@@ -0,0 +1,189 @@
|
||||
import {
|
||||
GA_DISABLE_KEY,
|
||||
readConsent,
|
||||
trackEmailClick,
|
||||
trackSocialClick,
|
||||
trackWhatsAppOpen,
|
||||
} from "./analytics";
|
||||
|
||||
/**
|
||||
* Testes de caminhos-base de lib/analytics.ts (complemento de analytics.test.ts):
|
||||
* modelo de rota de cada página (analyticsPagePath), cada condição que silencia o envio (sendEvent)
|
||||
* e a conversão do Google Ads (sendAdsConversion) com e sem etiqueta, com e sem consentimento.
|
||||
*/
|
||||
|
||||
const CONSENT_KEY = "evandro.analytics-consent.v1";
|
||||
const ADS_LABEL = "NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL";
|
||||
|
||||
beforeEach(() => {
|
||||
jest.replaceProperty(process.env, "NODE_ENV", "production");
|
||||
localStorage.setItem(CONSENT_KEY, "granted");
|
||||
delete window[GA_DISABLE_KEY];
|
||||
window.gtag = jest.fn();
|
||||
window.history.replaceState({}, "", "/");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
localStorage.clear();
|
||||
delete window.gtag;
|
||||
delete process.env[ADS_LABEL];
|
||||
window.history.replaceState({}, "", "/");
|
||||
});
|
||||
|
||||
function gtagCalls() {
|
||||
return (window.gtag as jest.Mock).mock.calls;
|
||||
}
|
||||
|
||||
describe("analyticsPagePath (via the page_path sent with each event)", () => {
|
||||
it.each([
|
||||
["/", "/"],
|
||||
["/servicos", "/servicos"],
|
||||
["/cases", "/cases"],
|
||||
["/curriculo", "/curriculo"],
|
||||
["/privacidade", "/privacidade"],
|
||||
["/ia", "/ia"],
|
||||
["/cases/", "/cases"],
|
||||
["/ia/?utm=x#y", "/ia"],
|
||||
["/servicos/criacao-de-sites", "/servicos/[slug]"],
|
||||
["/servicos/qualquer/coisa/mais", "/servicos/[slug]"],
|
||||
["/cases/sev-modaintima", "/cases/[slug]"],
|
||||
["/cases/ana%40example.com?x=1", "/cases/[slug]"],
|
||||
["/servicos-extra", "/other"],
|
||||
["/cases-extra/abc", "/other"],
|
||||
["/nao-existe", "/other"],
|
||||
])("path: location %s -> page_path %s", (location, expected) => {
|
||||
window.history.replaceState({}, "", location);
|
||||
|
||||
trackSocialClick({ network: "linkedin" });
|
||||
|
||||
expect(gtagCalls()).toHaveLength(1);
|
||||
expect(gtagCalls()[0][2]).toMatchObject({
|
||||
page_path: expected,
|
||||
page_location: `https://evandro.dev.br${expected}`,
|
||||
page_referrer: "",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("sendEvent: cada condição que silencia o envio", () => {
|
||||
it("path: gtag exists but is not a function -> nothing sent, no conversion, no error", () => {
|
||||
process.env[ADS_LABEL] = "abc123";
|
||||
window.gtag = "not-a-function" as never;
|
||||
|
||||
expect(() =>
|
||||
trackWhatsAppOpen({ service: "S", placement: "p" }),
|
||||
).not.toThrow();
|
||||
expect(() => trackEmailClick({ placement: "p" })).not.toThrow();
|
||||
});
|
||||
|
||||
it("path: stored consent is an unknown value -> treated as no consent", () => {
|
||||
localStorage.setItem(CONSENT_KEY, "yes");
|
||||
|
||||
trackSocialClick({ network: "linkedin" });
|
||||
|
||||
expect(readConsent()).toBeNull();
|
||||
expect(gtagCalls()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("path: storage throws -> readConsent returns null and nothing is sent", () => {
|
||||
jest.spyOn(Storage.prototype, "getItem").mockImplementation(() => {
|
||||
throw new Error("storage blocked");
|
||||
});
|
||||
|
||||
expect(readConsent()).toBeNull();
|
||||
trackSocialClick({ network: "linkedin" });
|
||||
|
||||
expect(gtagCalls()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("path: event counted -> one gtag call carrying the static params and the route template", () => {
|
||||
window.history.replaceState({}, "", "/cases/sev-modaintima?q=1#x");
|
||||
|
||||
trackEmailClick({ placement: "footer" });
|
||||
|
||||
expect(gtagCalls()).toEqual([
|
||||
[
|
||||
"event",
|
||||
"email_click",
|
||||
{
|
||||
send_to: "G-QTT9QT0T3S",
|
||||
placement: "footer",
|
||||
page_path: "/cases/[slug]",
|
||||
page_location: "https://evandro.dev.br/cases/[slug]",
|
||||
page_referrer: "",
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sendAdsConversion: etiqueta x consentimento", () => {
|
||||
it.each([
|
||||
["is unset", undefined],
|
||||
["is an empty string", ""],
|
||||
])(
|
||||
"path: label %s, consent granted -> only the GA4 event goes out",
|
||||
(_l, label) => {
|
||||
if (label !== undefined) process.env[ADS_LABEL] = label;
|
||||
|
||||
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
|
||||
trackEmailClick({ placement: "footer" });
|
||||
|
||||
expect(gtagCalls().map(([, name]) => name)).toEqual([
|
||||
"whatsapp_open",
|
||||
"email_click",
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
it("path: label set, consent denied -> nothing at all, not even the conversion", () => {
|
||||
process.env[ADS_LABEL] = "abc123";
|
||||
localStorage.setItem(CONSENT_KEY, "denied");
|
||||
|
||||
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
|
||||
trackEmailClick({ placement: "footer" });
|
||||
|
||||
expect(gtagCalls()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("path: label set, consent granted -> the conversion uses the Ads id and the label", () => {
|
||||
process.env[ADS_LABEL] = "xyz-789";
|
||||
|
||||
trackWhatsAppOpen({ service: "Contato", placement: "floating" });
|
||||
|
||||
expect(gtagCalls().map(([, name]) => name)).toEqual([
|
||||
"whatsapp_open",
|
||||
"conversion",
|
||||
]);
|
||||
expect(gtagCalls()[1][2]).toEqual({
|
||||
send_to: "AW-18432694647/xyz-789",
|
||||
});
|
||||
});
|
||||
|
||||
it("path: the conversion call throws -> the click handler still returns normally", () => {
|
||||
process.env[ADS_LABEL] = "abc123";
|
||||
window.gtag = jest.fn((_command: unknown, name: unknown) => {
|
||||
if (name === "conversion") throw new Error("ads blocked");
|
||||
});
|
||||
|
||||
expect(() =>
|
||||
trackWhatsAppOpen({ service: "Contato", placement: "floating" }),
|
||||
).not.toThrow();
|
||||
expect(gtagCalls().map(([, name]) => name)).toEqual([
|
||||
"whatsapp_open",
|
||||
"conversion",
|
||||
]);
|
||||
});
|
||||
|
||||
it("path: gtag disappears right after the event was counted -> the conversion is skipped silently", () => {
|
||||
process.env[ADS_LABEL] = "abc123";
|
||||
const gtag = jest.fn(() => {
|
||||
delete window.gtag;
|
||||
});
|
||||
window.gtag = gtag;
|
||||
|
||||
expect(() => trackEmailClick({ placement: "footer" })).not.toThrow();
|
||||
expect(gtag).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user