Skip to content

Commit 9347003

Browse files
committed
marketing: route posthog proxy under /_astro so it works on executor.sh
Cloud owns the executor.sh apex (custom domain) and only forwards an allow-list (including /_astro) to the marketing worker, so the prior /api/a proxy path 404d on the live domain and no events sent. Move the proxy to /_astro/_ph, which rides the forwarded prefix and is intercepted by the marketing middleware before any asset lookup. Also attach the analytics:capture listener synchronously so a click during posthog js async load is not dropped. Verified end to end: a capture POSTed through executor.sh/_astro/_ph/e/ lands in the Production project.
1 parent 30a39d3 commit 9347003

2 files changed

Lines changed: 28 additions & 25 deletions

File tree

apps/marketing/src/layouts/Layout.astro

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,29 +55,30 @@ const canonical = new URL(Astro.url.pathname, Astro.site ?? Astro.url).toString(
5555
// capture_pageview on if you want a denominator for conversion.
5656
const phKey = import.meta.env.PUBLIC_POSTHOG_KEY;
5757
if (phKey) {
58-
const phPath = (import.meta.env.PUBLIC_ANALYTICS_PATH ?? "a").replace(
59-
/^\/+|\/+$/g,
60-
"",
61-
);
62-
void import("posthog-js").then(({ default: posthog }) => {
58+
// api_host rides the `/_astro` prefix that the cloud edge forwards to
59+
// this worker on executor.sh; src/middleware.ts proxies it to PostHog.
60+
const posthogReady = import("posthog-js").then(({ default: posthog }) => {
6361
posthog.init(phKey, {
64-
api_host: `${window.location.origin}/api/${phPath}`,
62+
api_host: `${window.location.origin}/_astro/_ph`,
6563
ui_host: import.meta.env.PUBLIC_POSTHOG_HOST ?? "https://us.posthog.com",
6664
autocapture: false,
6765
capture_pageview: false,
6866
persistence: "localStorage",
6967
});
70-
// The copy handler (in index.astro) is a separate bundle, so it asks
71-
// for a capture via a DOM event rather than reaching for a global.
72-
window.addEventListener("analytics:capture", (e) => {
73-
const detail = (
74-
e as CustomEvent<{
75-
event: string;
76-
properties?: Record<string, unknown>;
77-
}>
78-
).detail;
79-
posthog.capture(detail.event, detail.properties);
80-
});
68+
return posthog;
69+
});
70+
// The copy handler (in index.astro) is a separate bundle, so it asks for
71+
// a capture via a DOM event rather than reaching for a global. Attached
72+
// synchronously so a click during PostHog's async load isn't missed; the
73+
// capture waits on the init promise.
74+
window.addEventListener("analytics:capture", (e) => {
75+
const detail = (
76+
e as CustomEvent<{
77+
event: string;
78+
properties?: Record<string, unknown>;
79+
}>
80+
).detail;
81+
void posthogReady.then((posthog) => posthog.capture(detail.event, detail.properties));
8182
});
8283
}
8384
</script>

apps/marketing/src/middleware.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import type { MiddlewareHandler } from "astro";
22

3-
// PostHog reverse proxy — the browser SDK targets a build-randomized
4-
// first-party path and we forward to PostHog's ingest + asset hosts. Keeps
5-
// events flowing past adblockers that match *.posthog.com. See
3+
// PostHog reverse proxy — the browser SDK targets a first-party path and we
4+
// forward to PostHog's ingest + asset hosts. Keeps events flowing past
5+
// adblockers that match *.posthog.com. See
66
// https://posthog.com/docs/advanced/proxy/cloudflare
7-
7+
//
8+
// The path MUST sit under a prefix that the cloud worker's edge forwards to
9+
// this worker. On the production apex (executor.sh) the cloud worker owns the
10+
// custom domain and only proxies an allow-list to executor-marketing; `/api/*`
11+
// stays in cloud (it has its own posthog proxy on a randomized path), so a
12+
// top-level `/api/...` path here 404s. `/_astro` IS forwarded, so we ride it.
813
const POSTHOG_INGEST_HOST = "us.i.posthog.com";
914
const POSTHOG_ASSETS_HOST = "us-assets.i.posthog.com";
10-
const POSTHOG_PROXY_PATH = `/api/${(import.meta.env.PUBLIC_ANALYTICS_PATH ?? "a").replace(
11-
/^\/+|\/+$/g,
12-
"",
13-
)}`;
15+
const POSTHOG_PROXY_PATH = "/_astro/_ph";
1416

1517
export const onRequest: MiddlewareHandler = async (context, next) => {
1618
const { pathname } = new URL(context.request.url);

0 commit comments

Comments
 (0)