Skip to content

Commit

Permalink
measurement plan
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderkirtzel committed Sep 14, 2022
1 parent a78af7a commit 2200ab5
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 4 deletions.
36 changes: 32 additions & 4 deletions 220916-code_talks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@ We’ll walk through real-world examples to give you not just inspiration but al

## The problem

To most organizations tracking implementation today is a highly error-prone downstream task that nobody likes. Most of the time there is no universal approach to it. It just grows historically and hysterically with the number of new marketing tools and features. The lack of strategy and documentation creates data, that is neither reliable nor sustainable. It also makes it hard to govern data collection in terms of data privacy. Instead of installing another plugin,or fixing the next tracking error and be annoyed, what about starting with a new approach?
To most organizations tracking implementation today is a highly error-prone downstream task that nobody likes. Most of the time there is no universal approach to it. It just grows historically and hysterically with the number of new marketing tools and features. The lack of strategy and documentation creates data, that is neither reliable nor sustainable. It also makes it hard to govern data collection in terms of data privacy. Instead of installing another plugin, or fixing the next tracking error and be annoyed, what about starting with a new approach?

### Data lifecycle

0. Using
1. Reporting
2. Analyzing
3. Storing
4. Distributing
5. Collecting
6. Implementing
7. Planning <-- Start here

## Measurement plan

Expand All @@ -34,10 +45,21 @@ Start **together**: Product managers, marketeers, engineers etc. need a **common

XXX result of a measurement plan overview

> Recommendation: Don't just make a plan. Work with it and iterate.
> Recommendation: Have a plan. Work with it and iterate.
## Implementation layer

### Data lifecycle

0. Using
1. Reporting
2. Analyzing
3. Storing
4. Distributing
5. Collecting
6. Implementing <-- We're here now
7. Planning

- central source of truth
- documentation
- living standard
Expand Down Expand Up @@ -89,9 +111,15 @@ XXX example measurement.json

> Recommendation: Listen to the **Meet the analytics stack** episode "[Why tracking implementation is still hard work and how to improve](../220907-meet_the_analytics_stack/))" with [Timo Dechau](https://www.linkedin.com/in/timo-dechau/) for a deep dive on event contexts.
## walker.js
## @elbwalker/walker.js

Descriptive markup language based on HTML-attributes.

Benefits XXX
- Creates the **event context**
- Handles the **triggers**
- Orders the **race conditions**
- Distributes to **destinations**
- It's **open source**

1. entity (`data-elb="XXX"`)
2. action (`data-elbaction="XXX"`)
Expand Down
Binary file added 220916-code_talks/intro_slide.pdf
Binary file not shown.
179 changes: 179 additions & 0 deletions 220916-code_talks/measurementplan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { Measurement } from "./types";

const plan: Measurement.Plan = {
entities: {
page: {
name: "Page",
description: "A regular page that can be called diretly",
actions: {
view: {
name: "Pageview",
description: "The well known pageview on each route change",
properties: [],
sources: { web: { required: true } },
trigger: { type: "load" },
type: "core",
},
},
properties: {},
owners: ["alexander"],
},
cta: {
name: "CTA",
description: "Engage users to use our products and services",
actions: {
impression: {
name: "CTA impression",
description: "",
properties: [
{ id: "title", required: true },
{ id: "position", required: true },
],
sources: { web: { required: true } },
trigger: { type: "visible" },
type: "core",
},
start: {
name: "CTA start",
description: "Click 'get started' button",
properties: [
{ id: "title", required: true },
{ id: "position", required: true },
],
sources: { web: { required: true } },
trigger: { type: "click" },
type: "core",
},
github: {
name: "CTA github",
description: "Click button 'Check it out on GithHub'",
properties: [
{ id: "title", required: true },
{ id: "position", required: true },
],
sources: { web: { required: true } },
trigger: { type: "click" },
type: "core",
},
},
properties: {
title: {
name: "Title headline",
type: "string",
example: "Ready to dive in?",
},
position: {
name: "Placement of the CTA on a page",
type: "string",
example: "footer",
},
},
owners: ["alexander"],
},
blog: {
name: "Blog",
description: "Educational content about the usage of out tools",
actions: {
impression: {
name: "Blog impression",
description: "",
properties: [{ id: "id", required: true }],
sources: { web: { required: true } },
trigger: { type: "visible" },
type: "additional",
},
click: {
name: "Blog click",
description: "",
properties: [{ id: "id", required: true }],
sources: { web: { required: true } },
trigger: { type: "click" },
type: "additional",
},
view: {
name: "Blog view",
description: "Load of a fully detailed blog article",
properties: [
{ id: "id", required: true },
{ id: "title", required: true },
{ id: "date", required: true },
{ id: "category", required: true },
{ id: "author", required: true },
{ id: "readingTime", required: true },
],
sources: { web: { required: true } },
trigger: { type: "load" },
type: "core",
},
read: {
name: "Blog read",
description: "As soon as someone sees the end of an article",
properties: [{ id: "id", required: true }],
sources: { web: { required: true } },
trigger: { type: "visible" },
type: "core",
},
},
properties: {
id: {
name: "Path of the article",
type: "string",
example: "/blog/elbwalker-event-concept",
},
title: {
name: "Catchy title",
type: "string",
example: "The elbwalker event concept",
},
date: {
name: "When the article was published",
type: "string",
example: "2022-03-09T00:00:00.000Z",
},
category: {
name: "The main category the blog article belongs to",
type: "string",
example: "Product",
},
author: {
name: "Name of the author",
type: "string",
example: "Ayla",
},
readingTime: {
name: "The estimated reading time",
type: "number",
example: "6",
},
},
owners: ["alexander"],
},
},
sources: {
web: {
name: "elbwalker.com",
type: "web",
owners: ["alexander"],
},
},
destinations: {
datalake: {
name: "",
type: "event-pipe",
owners: ["alexander"],
events: {
"*": {
"*": {
consent: ["statistic"],
},
},
},
},
},
globals: {},
version: 1,
users: {
alexander: { name: "Alexander" },
ayla: { name: "Ayla" },
},
};
123 changes: 123 additions & 0 deletions 220916-code_talks/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
export namespace Measurement {
export interface Plan {
entities: Entities;
sources: Sources;
destinations: Destinations;
globals: Properties;
version: number;
users: Users;
}

interface Entities {
[entityId: string]: Entity;
}

interface Entity {
name: string;
description: string;
actions: Actions;
properties: Properties;
owners: Array<UserId>;
}

interface Actions {
[actionId: string]: Action;
}

interface Action {
name: string;
description: string;
properties: Array<PropertyLink>;
sources: ActionSources;
trigger: Trigger;
type: ActionType;
}
type ActionType = "core" | "additional";

interface ActionSources {
[sourceId: string]: SourceLink;
}

type ConsentList = Array<ConsentId>;
type ConsentId = string;

interface Consent {
id: ConsentId;
name: string;
}

interface SourceLink {
required: boolean;
}

interface PropertyLink {
id: string;
required: boolean;
}

interface Properties {
[propertyId: string]: Property;
}

interface Property {
name: string;
type: PropertyType;
consent?: ConsentList;
example: string; // @TODO corresponding to type
}

type PropertyType = string | number | boolean;

interface Trigger {
type: TriggerType;
}

type TriggerType = "load" | "click" | "visible" | "hover" | "submit";

interface Sources {
[sourceId: string]: Source;
}

interface Source {
name: string;
type: SourceType;
owners: Array<UserId>;
}

type SourceType = "app" | "other" | "server" | "web";

interface Destinations {
[destinationId: string]: Destination;
}

interface Destination {
name: string;
type: DestinationType;
owners: Array<UserId>;
events: DestinationEvents;
}

interface DestinationEvents {
[entityId: string]: { [actionId: string]: DestinationEvent };
}

interface DestinationEvent {
consent: ConsentList;
}

type DestinationType =
| "event-pipe"
| "google-ga4"
| "google-gtm"
| "plausible"
| "custom";

interface Users {
[userId: UserId]: User;
}
type UserId = string;

interface User {
name: string;
}
}

0 comments on commit 2200ab5

Please sign in to comment.