Skip to content

Commit

Permalink
feat(posthog): add custom event for cookie consent and unify event ha…
Browse files Browse the repository at this point in the history
…ndling (#612)

* feat(posthog): add custom event for cookie consent and unify event handling

* feat(posthog): update arguments and typing
  • Loading branch information
rbrtrfl authored Feb 21, 2024
1 parent aaab69d commit 05354b2
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 29 deletions.
15 changes: 8 additions & 7 deletions app/routes/action.send-rating.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { json, redirect } from "@remix-run/node";
import { BannerState } from "~/components/UserFeedback";
import { userRatingFieldname } from "~/components/UserFeedback/RatingBox";
import { getSessionForContext } from "~/services/session.server";
import { config } from "~/services/env/web";
import { bannerStateName } from "~/services/feedback/handleFeedback";
import { getPosthogClient } from "~/services/analytics/posthogClient.server";
import { sendCustomEvent } from "~/services/analytics/customEvent";

export const loader = () => redirect("/");

Expand All @@ -32,11 +31,13 @@ export const action = async ({ request }: ActionFunctionArgs) => {

const headers = { "Set-Cookie": await commitSession(session) };

getPosthogClient()?.capture({
distinctId: config().ENVIRONMENT,
event: "rating given",
// eslint-disable-next-line camelcase
properties: { wasHelpful: userRatings[url], $current_url: url, context },
sendCustomEvent({
eventName: "rating given",
request,
properties: {
wasHelpful: userRatings[url],
context,
},
});

return clientJavaScriptAvailable
Expand Down
3 changes: 1 addition & 2 deletions app/routes/action.set-analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const { searchParams } = new URL(request.url);
const clientJavaScriptAvailable = searchParams.get("js");

const cookie = await consentCookieFromRequest({ request });
const headers = { "Set-Cookie": cookie };
const headers = await consentCookieFromRequest({ request });

if (clientJavaScriptAvailable) {
return json({ success: true }, { headers });
Expand Down
2 changes: 1 addition & 1 deletion app/routes/cookie-einstellungen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
}

export async function action({ request }: ActionFunctionArgs) {
const headers = { "Set-Cookie": await consentCookieFromRequest({ request }) };
const headers = await consentCookieFromRequest({ request });
return redirect("/cookie-einstellungen/erfolg", { headers });
}

Expand Down
9 changes: 7 additions & 2 deletions app/routes/shared/step.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
deleteFromArrayInplace,
} from "~/services/session.server/arrayDeletion";
import type { StrapiMeta } from "~/services/cms/models/StrapiMeta";
import { hasTrackingConsent } from "~/services/analytics/gdprCookie.server";

const structureCmsContent = (
formPageContent: z.infer<
Expand Down Expand Up @@ -301,8 +302,12 @@ export const action = async ({ request }: ActionFunctionArgs) => {
});

const customEventName = flowController.getMeta(stepId)?.customEventName;
if (customEventName)
void sendCustomEvent(customEventName, validationResult.data, request);
if (customEventName && (await hasTrackingConsent({ request })))
sendCustomEvent({
request,
eventName: customEventName,
properties: { context: validationResult.data },
});

const returnTo = formData.get("_returnTo");
const destination =
Expand Down
23 changes: 14 additions & 9 deletions app/services/analytics/customEvent.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { hasTrackingConsent } from "./gdprCookie.server";
import { config } from "../env/web";
import { parse } from "cookie";
import { getPosthogClient } from "./posthogClient.server";

function idFromCookie(request: Request) {
// console.log("request", request)
// Note: can't use cookie.parse(): https://github.com/remix-run/remix/discussions/5198
// Returns ENVIRONMENT if posthog's distinct_id can't be extracted
const { POSTHOG_API_KEY, ENVIRONMENT } = config();
Expand All @@ -14,20 +14,25 @@ function idFromCookie(request: Request) {
return phCookieObject["distinct_id"] ?? ENVIRONMENT;
}

export async function sendCustomEvent(
eventName: string,
context: Record<string, any>,
request: Request,
) {
if (!(await hasTrackingConsent({ request }))) return;

export function sendCustomEvent({
request,
eventName,
properties,
}: {
request: Request;
eventName: string;
properties?: Record<
string,
string | boolean | Record<string, string | boolean>
>;
}) {
getPosthogClient()?.capture({
distinctId: idFromCookie(request),
event: eventName,
properties: {
// eslint-disable-next-line camelcase
$current_url: new URL(request.url).pathname,
...context,
...properties,
},
});
}
10 changes: 9 additions & 1 deletion app/services/analytics/gdprCookie.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createCookie } from "@remix-run/node";
import { acceptCookiesFieldName } from "./Analytics";
import { useSecureCookie } from "~/util/useSecureCookie";
import { sendCustomEvent } from "./customEvent";

export const consentCookieName = "gdpr-consent";

Expand Down Expand Up @@ -38,9 +39,16 @@ async function createTrackingCookie({
}: CookieArgs & { consent?: boolean }) {
const cookie = await parseTrackingCookie({ request });
const stringifiedConsentValue = consent ? "true" : "false";
if (cookie[acceptCookiesFieldName] === stringifiedConsentValue)
return {} as HeadersInit;
cookie[acceptCookiesFieldName] =
consent === undefined ? undefined : stringifiedConsentValue;
return gdprCookie.serialize(cookie);
sendCustomEvent({
eventName: "cookie consent given",
request,
properties: { consent: stringifiedConsentValue },
});
return { "Set-Cookie": await gdprCookie.serialize(cookie) } as HeadersInit;
}

export async function consentCookieFromRequest({
Expand Down
11 changes: 4 additions & 7 deletions app/services/feedback/handleFeedback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {
} from "~/components/UserFeedback/FeedbackFormBox";
import { userRatingFieldname } from "~/components/UserFeedback/RatingBox";
import { validationError } from "remix-validated-form";
import { config } from "../env/web";
import { type Session, redirect } from "@remix-run/node";
import { getPosthogClient } from "../analytics/posthogClient.server";
import { sendCustomEvent } from "../analytics/customEvent";

export const bannerStateName = "bannerState";

Expand All @@ -30,14 +29,12 @@ export const handleFeedback = async (formData: FormData, request: Request) => {
return validationError(result.error, result.submittedData);
}
bannerState[pathname] = BannerState.FeedbackGiven;
getPosthogClient()?.capture({
distinctId: config().ENVIRONMENT,
event: "feedback given",
sendCustomEvent({
eventName: "feedback given",
request,
properties: {
wasHelpful: userRating[pathname],
feedback: result.data?.feedback ?? "",
// eslint-disable-next-line camelcase
$current_url: pathname,
context,
},
});
Expand Down

0 comments on commit 05354b2

Please sign in to comment.