Skip to content

Commit

Permalink
Tavano/standardize flags (#401)
Browse files Browse the repository at this point in the history
* standardize flags

* fmt

* get cookie client side

* fmt

* unused flags

* add try catch

* add try catch

* get cookie name from const

* fmt

* remove local
  • Loading branch information
guitavano authored Feb 22, 2024
1 parent aa2f89c commit dbf2260
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 37 deletions.
8 changes: 5 additions & 3 deletions analytics/loaders/DecoAnalyticsScript.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getFlagsFromCookies } from "../../utils/cookie.ts";
import { getFlagsFromRequest } from "../../utils/cookie.ts";
import { Script } from "../../website/types.ts";
import { AppContext } from "../mod.ts";
import { scriptAsDataURI } from "../../utils/dataURI.ts";
Expand Down Expand Up @@ -47,10 +47,12 @@ const loader = (
const preconnectLink =
'<link rel="preconnect" href="https://plausible.io/api/event" crossorigin="anonymous" />';

const _flags = getFlagsFromCookies(req);
const _flags = getFlagsFromRequest(req);
const flags: Record<string, string | boolean> = {};
_flags.forEach((flag) => flags[flag.flagName] = flag.flagActive);
_flags.forEach((flag) => flags[flag.name] = flag.value);

// if you want to test it local, add ".local" to src
// example: /script.manual.local.js
const plausibleScript = `<script ${
props.defer ? "defer" : ""
} data-exclude="/proxy" ${
Expand Down
34 changes: 22 additions & 12 deletions utils/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { getCookies, getSetCookies, setCookie } from "std/http/cookie.ts";
import { DECO_MATCHER_PREFIX } from "deco/blocks/matcher.ts";
import { tryOrDefault } from "deco/utils/object.ts";
import { Flag } from "deco/types.ts";
import { DECO_SEGMENT } from "deco/runtime/fresh/middlewares/3_main.ts";

export const getFlagsFromCookies = (req: Request) => {
const flags = [];
export const getFlagsFromRequest = (req: Request) => {
const cookies = getCookies(req.headers);
return getFlagsFromCookies(cookies);
};

export const getFlagsFromCookies = (cookies: Record<string, string>) => {
const flags: Flag[] = [];
const segment = cookies[DECO_SEGMENT]
? tryOrDefault(
() => JSON.parse(decodeURIComponent(atob(cookies[DECO_SEGMENT]))),
{},
)
: {};

segment.active?.forEach((flag: string) =>
flags.push({ name: flag, value: true })
);
segment.inactiveDrawn?.forEach((flag: string) =>
flags.push({ name: flag, value: false })
);

for (const [key, value] of Object.entries(cookies)) {
if (key.startsWith(DECO_MATCHER_PREFIX)) {
const flagName = atob(
value.slice(value.lastIndexOf("=") + 1, value.indexOf("@")),
);
const flagActive = value.at(-1) === "1";
flags.push({ flagName, flagActive });
}
}
return flags;
};

Expand Down
54 changes: 32 additions & 22 deletions website/components/Events.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Head } from "$fresh/runtime.ts";
import { DECO_SEGMENT } from "deco/runtime/fresh/middlewares/3_main.ts";
import { type AnalyticsEvent, type Deco } from "../../commerce/types.ts";
import { scriptAsDataURI } from "../../utils/dataURI.ts";
import { Flag } from "deco/types.ts";

type EventHandler = (event?: AnalyticsEvent) => void | Promise<void>;

Expand Down Expand Up @@ -28,29 +30,33 @@ declare global {
* This function handles all ecommerce analytics events.
* Add another ecommerce analytics modules here.
*/
const snippet = ({ flags, page }: Deco) => {
const appendSessionFlags = () => {
const knownFlags = new Set(flags.map((f) => f.name));
const cookies = document.cookie.split(";");

for (let i = 0; i < cookies.length; i++) {
const ck = cookies[i].trim();

if (ck.startsWith("deco_matcher_")) {
const name = atob(ck.slice(ck.lastIndexOf("=") + 1, ck.indexOf("@")));
const value = ck.at(-1) === "1" ? true : false;

if (knownFlags.has(name)) continue;

flags.push({ name, value });
}
const snippet = (
{ deco: { page }, segmentCookie }: { deco: Deco; segmentCookie: string },
) => {
const cookie = document.cookie;
const out: Record<string, string> = {};
if (cookie !== null) {
const c = cookie.split(";");
for (const kv of c) {
const [cookieKey, ...cookieVal] = kv.split("=");
const key = cookieKey.trim();
out[key] = cookieVal.join("=");
}
};
}

try {
appendSessionFlags();
} catch (error) {
console.error(error);
const flags: Flag[] = [];
if (out[segmentCookie]) {
try {
const segment = JSON.parse(decodeURIComponent(atob(out[segmentCookie])));
segment.active?.forEach((flag: string) =>
flags.push({ name: flag, value: true })
);
segment.inactiveDrawn?.forEach((flag: string) =>
flags.push({ name: flag, value: false })
);
} catch {
console.error("Error parsing deco_segment cookie");
}
}

const target = new EventTarget();
Expand Down Expand Up @@ -82,7 +88,11 @@ const snippet = ({ flags, page }: Deco) => {
function Events({ deco }: { deco: Deco }) {
return (
<Head>
<script defer id="deco-events" src={scriptAsDataURI(snippet, deco)} />
<script
defer
id="deco-events"
src={scriptAsDataURI(snippet, { deco, segmentCookie: DECO_SEGMENT })}
/>
</Head>
);
}
Expand Down

0 comments on commit dbf2260

Please sign in to comment.