Skip to content

Commit cca1079

Browse files
committed
wip
1 parent b30d46d commit cca1079

File tree

3 files changed

+132
-144
lines changed

3 files changed

+132
-144
lines changed

packages/browser/README.md

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Analytics Next (aka Analytics 2.0) is the latest version of Segment’s JavaScri
77
- [🏎️ Quickstart](#-quickstart)
88
- [💡 Using with Segment](#-using-with-segment)
99
- [💻 Using as an `npm` package](#-using-as-an-npm-package)
10-
- [🔌 Plugins](#-plugins)
10+
- [🔌 Architecture](#-architecture--plugins)
1111
- [🐒 Development](#-development)
1212

1313
---
@@ -187,8 +187,8 @@ declare global {
187187
}
188188
```
189189

190-
## Architecture
191-
- Plugin Architecture: [Plugin Architecture](architecture/plugin-architecture.md)
190+
## 🔌 Architecture & Plugins
191+
- See [ARCHITECTURE.md](architecture/ARCHITECTURE.md)
192192

193193
## 🐒 Development
194194

@@ -209,56 +209,5 @@ Then, make your changes and test them out in the test app!
209209

210210
<img src="https://user-images.githubusercontent.com/2866515/135407053-7561d522-b969-484d-8d3a-6f1c4d9c025b.gif" alt="Example of the development app" width="500px">
211211

212-
# 🔌 Plugins
213-
214-
When developing against Analytics Next you will likely be writing plugins, which can augment functionality and enrich data. Plugins are isolated chunks which you can build, test, version, and deploy independently of the rest of the codebase. Plugins are bounded by Analytics Next which handles things such as observability, retries, and error management.
215-
216-
Plugins can be of two different priorities:
217-
218-
1. **Critical**: Analytics Next should expect this plugin to be loaded before starting event delivery
219-
2. **Non-critical**: Analytics Next can start event delivery before this plugin has finished loading
220-
221-
and can be of five different types:
222-
223-
1. **Before**: Plugins that need to be run before any other plugins are run. An example of this would be validating events before passing them along to other plugins.
224-
2. **After**: Plugins that need to run after all other plugins have run. An example of this is the segment.io integration, which will wait for destinations to succeed or fail so that it can send its observability metrics.
225-
3. **Destination**: Destinations to send the event to (ie. legacy destinations). Does not modify the event and failure does not halt execution.
226-
4. **Enrichment**: Modifies an event, failure here could halt the event pipeline.
227-
5. **Utility**: Plugins that change Analytics Next functionality and don't fall into the other categories.
228-
229-
Here is an example of a simple plugin that would convert all track events event names to lowercase before the event gets sent through the rest of the pipeline:
230-
231-
```ts
232-
import type { Plugin } from '@segment/analytics-next'
233-
234-
export const lowercase: Plugin = {
235-
name: 'Lowercase Event Name',
236-
type: 'before',
237-
version: '1.0.0',
238-
239-
isLoaded: () => true,
240-
load: () => Promise.resolve(),
241-
242-
track: (ctx) => {
243-
ctx.event.event = ctx.event.event.toLowerCase()
244-
return ctx
245-
}
246-
}
247-
248-
analytics.register(lowercase)
249-
```
250-
251-
For further examples check out our [existing plugins](/packages/browser/src/plugins).
252-
253-
## 🧪 QA
254-
Feature work and bug fixes should include tests. Run all [Jest](https://jestjs.io) tests:
255-
```
256-
$ yarn test
257-
```
258-
Lint all with [ESLint](https://github.com/typescript-eslint/typescript-eslint/):
259-
```
260-
$ yarn lint
261-
```
262-
263212

264213

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
## Analytics.js Plugin Architecture
2+
3+
> [!IMPORTANT]
4+
> This doc may get out-of-date. Please prefer to use and link to Segment documentation for the most up-to-date information. It would be advisable to move this doc to https://segment.com/docs/connections/sources/catalog/libraries/website/javascript, so there is a single source of truth.
5+
6+
### Event Flow Diagram
7+
More details on plugin architecture can be found here:
8+
https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/#plugins-and-source-middleware
9+
10+
### You can use the [vscode mermaid extension](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) to preview the following diagram code block inside of vscode, or copy and paste into the [mermaid live editor](https://mermaid.live/).
11+
12+
```mermaid
13+
graph TD
14+
subgraph Event Creation
15+
A[analytics.track/page/identify] --> B[Event Factory]
16+
B --> C[Event Queue]
17+
end
18+
19+
subgraph Plugin Pipeline
20+
C --> D[Before Plugins e.g add page context]
21+
D --> E[Enrichment Plugins]
22+
E --> F[Destination Plugins e.g Segment.io]
23+
F --> G[After Plugins]
24+
end
25+
26+
subgraph Plugin Types Details
27+
I[Before Plugins<br/>Priority: Critical<br/>Example: Event Validation] --- D
28+
J[Enrichment Plugins<br/>Priority: Critical<br/>Parallel Execution<br/>Can Modify Events<br/>Example: Add User Agent] --- E
29+
K[Destination Plugins<br/>Parallel Execution<br/>Cannot Modify Events<br/>Example: Google Analytics] --- F
30+
L[After Plugins<br/>Example: Metrics Collection] --- G
31+
end
32+
33+
subgraph Notes
34+
M[Plugin Priorities]
35+
N[Critical - Must load before<br/>event delivery starts]
36+
O[Non-Critical - Can load<br/>after event delivery starts]
37+
M --> N
38+
M --> O
39+
end
40+
```
41+
42+
### Plugin Types Explanation
43+
[This information is also available in the Segment documentation](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/#plugins-and-source-middleware)
44+
45+
1. **Before Plugins** (see [Example](#example-plugin-implementation))
46+
- Run before any other plugins
47+
- Critical priority - block event pipeline until `.load()` resolves
48+
- Use cases: Event validation, data transformation
49+
- Example: Event validation before passing to other plugins)
50+
51+
A. **Source Middleware** (see [Example](#example-source-middleware-implementation))
52+
- **Source Middleware is just a light API wrapper around a "Before" type plugin Plugin**
53+
- Source Middleware is the legacy API (pre-analytics next). It's less verbose than the full plugin API, but a bit less powerful. It is functionally equivalent to a "Before" type plugin.
54+
55+
2. **Enrichment Plugins**
56+
- Functionally Identitical to "before" plugins, but run after them. Before plugins are typically used internally (e.g adding page info), but there's no hard and fast rule.
57+
58+
3. **Destination Plugins**
59+
- Run after enrichment
60+
- Cannot modify the event
61+
- Execute in parallel
62+
- Failures do not halt pipeline
63+
- Example: Segment.io, Google Analytics, Mixpanel
64+
65+
4. **After Plugins (uncommon)**
66+
- Run after all other plugins complete
67+
- Use cases: Metrics, logging
68+
- Example: segment.io plugin for observability metrics
69+
70+
5. **Utility Plugins**
71+
- Executes only once during the analytics.js bootstrap. Gives you access to the analytics instance using the plugin's load() method. This doesn't allow you to modify events.
72+
- Do not directly process events
73+
- Example: some plugin that registers a bunch of analytics event listeners (e.g. analytics.on('track', ...) and reports them to an external system)
74+
75+
### Example: Plugin Implementation
76+
```ts
77+
export const myPlugin = {
78+
name: 'Do stuff'
79+
type: 'before',
80+
isLoaded: () => true,
81+
load: () => Promise.resolve(),
82+
// drop page events with a specific title
83+
page: (ctx) => {
84+
if (ctx.properties.title === 'some title') {
85+
return null
86+
}
87+
}
88+
// lowercase all track event names
89+
track: (ctx) => {
90+
ctx.event.event = ctx.event.event.toLowerCase()
91+
return ctx
92+
}
93+
}
94+
analytics.register(myPlugin)
95+
```
96+
### Example: Source Middleware Implementation
97+
```ts
98+
analytics.addSourceMiddleware(({ payload, next }) => {
99+
const { event } = payload.obj.context
100+
if (event.type === 'track') {
101+
// change the event name to lowercase
102+
event.event = event.event.toLowerCase()
103+
} else if (event.type === 'page') {
104+
// drop any page events with no title
105+
if (event.properties.title === 'some title') {
106+
return null
107+
}
108+
}
109+
next(payload)
110+
})
111+
```
112+
113+
### Event Flow Example
114+
115+
When `analytics.track()` is called:
116+
117+
1. Event is created via Event Factory
118+
2. Event enters the queue
119+
3. Before plugins validate/transform
120+
4. Enrichment plugins add data in parallel
121+
5. Destination plugins receive the event in parallel (including Segment.io plugin)
122+
6. Any after plugins handle post-processing (e.g. metrics collection)
123+
124+
### Plugin Priorities
125+
126+
- **Critical Plugins**: Must be loaded before event delivery starts
127+
- Example: Before plugins, Validation plugins
128+
- **Non-Critical Plugins**: Can load after event delivery begins
129+
- Example: Destination plugins

packages/browser/architecture/plugin-architecture.md

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)