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
+63
-12
@@ -1,4 +1,5 @@
|
||||
export const GA_MEASUREMENT_ID = "G-QTT9QT0T3S";
|
||||
export const GOOGLE_ADS_ID = "AW-18432694647";
|
||||
export const CONSENT_STORAGE_KEY = "evandro.analytics-consent.v1";
|
||||
export const GA_DISABLE_KEY = "ga-disable-G-QTT9QT0T3S";
|
||||
|
||||
@@ -30,6 +31,7 @@ function analyticsPagePath(): string {
|
||||
case "/cases":
|
||||
case "/curriculo":
|
||||
case "/privacidade":
|
||||
case "/ia":
|
||||
return path;
|
||||
default:
|
||||
// Route templates keep arbitrary slugs and personal data out of metrics.
|
||||
@@ -39,16 +41,14 @@ function analyticsPagePath(): string {
|
||||
}
|
||||
}
|
||||
|
||||
/** Measures an attempted handoff, not an opened app, delivered message or lead.
|
||||
type EventParams = Record<string, string>;
|
||||
|
||||
/**
|
||||
* Sends one GA4 event only while the visitor has granted consent; every other state is silent.
|
||||
* Callers must supply static labels, never form values or destination URLs.
|
||||
* Returns true when the event was handed to gtag, so the Ads conversion is only sent for a counted click.
|
||||
*/
|
||||
export function trackWhatsAppOpen({
|
||||
service,
|
||||
placement,
|
||||
}: {
|
||||
service: string;
|
||||
placement: string;
|
||||
}): void {
|
||||
function sendEvent(name: string, params: EventParams): boolean {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" ||
|
||||
typeof window === "undefined" ||
|
||||
@@ -56,21 +56,72 @@ export function trackWhatsAppOpen({
|
||||
window[GA_DISABLE_KEY] === true ||
|
||||
typeof window.gtag !== "function"
|
||||
) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const pagePath = analyticsPagePath();
|
||||
window.gtag("event", "whatsapp_open", {
|
||||
window.gtag("event", name, {
|
||||
send_to: GA_MEASUREMENT_ID,
|
||||
service,
|
||||
placement,
|
||||
...params,
|
||||
page_path: pagePath,
|
||||
// Override gtag's URL defaults so query/hash/referrer data cannot leak.
|
||||
page_location: `https://evandro.dev.br${pagePath}`,
|
||||
page_referrer: "",
|
||||
});
|
||||
return true;
|
||||
} catch {
|
||||
// Analytics must never interrupt navigation. Dropped events are not replayed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Google Ads conversion for the same click, only when a conversion label is configured.
|
||||
* Without NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL nothing is sent to Ads.
|
||||
*/
|
||||
function sendAdsConversion(): void {
|
||||
const label = process.env.NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL;
|
||||
if (!label) return;
|
||||
try {
|
||||
window.gtag?.("event", "conversion", {
|
||||
send_to: `${GOOGLE_ADS_ID}/${label}`,
|
||||
});
|
||||
} catch {
|
||||
// Same rule as above: a blocked tag never interrupts navigation.
|
||||
}
|
||||
}
|
||||
|
||||
/** Measures an attempted handoff, not an opened app, delivered message or lead. */
|
||||
export function trackWhatsAppOpen({
|
||||
service,
|
||||
placement,
|
||||
}: {
|
||||
service: string;
|
||||
placement: string;
|
||||
}): void {
|
||||
if (sendEvent("whatsapp_open", { service, placement })) sendAdsConversion();
|
||||
}
|
||||
|
||||
/** Measures a click on a mailto: link, not a sent e-mail. */
|
||||
export function trackEmailClick({ placement }: { placement: string }): void {
|
||||
if (sendEvent("email_click", { placement })) sendAdsConversion();
|
||||
}
|
||||
|
||||
/** Measures a click on a social profile; `network` is a static name such as "linkedin". */
|
||||
export function trackSocialClick({ network }: { network: string }): void {
|
||||
sendEvent("social_click", { network });
|
||||
}
|
||||
|
||||
/** Measures a click on the résumé PDF download. */
|
||||
export function trackCvDownload({ placement }: { placement: string }): void {
|
||||
sendEvent("cv_download", { placement });
|
||||
}
|
||||
|
||||
/** O rodapé pede a reabertura da barra de cookies; quem a monta (GoogleAnalytics) escuta este evento. */
|
||||
export const OPEN_COOKIE_PREFERENCES_EVENT = "evandro:open-cookie-preferences";
|
||||
|
||||
export function openCookiePreferences(): void {
|
||||
if (typeof window === "undefined") return;
|
||||
window.dispatchEvent(new Event(OPEN_COOKIE_PREFERENCES_EVENT));
|
||||
}
|
||||
Reference in new issue
Block a user