From 9282de16af060ab68b7a69afd9a251377b4ca4d7 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Sun, 1 Jun 2025 00:53:12 +0900 Subject: [PATCH 1/3] docs: improve documentation --- docs/src/content/en/installation.mdx | 14 +- docs/src/content/ko/_meta.ts | 47 ++-- .../ko/{quick-start.mdx => basic-example.mdx} | 0 docs/src/content/ko/create-tracker.mdx | 133 +++++----- docs/src/content/ko/index.mdx | 229 +++++------------- docs/src/content/ko/installation.mdx | 18 +- .../content/ko/{hook.mdx => useTracker.mdx} | 7 +- docs/src/content/ko/why-event-tracker.mdx | 186 ++++++++++++++ 8 files changed, 349 insertions(+), 285 deletions(-) rename docs/src/content/ko/{quick-start.mdx => basic-example.mdx} (100%) rename docs/src/content/ko/{hook.mdx => useTracker.mdx} (94%) create mode 100644 docs/src/content/ko/why-event-tracker.mdx diff --git a/docs/src/content/en/installation.mdx b/docs/src/content/en/installation.mdx index d2c9a98..4d9af8e 100644 --- a/docs/src/content/en/installation.mdx +++ b/docs/src/content/en/installation.mdx @@ -2,18 +2,6 @@ Using npm: -```bash +```shell npm2yarn npm install @offlegacy/event-tracker ``` - -Using yarn: - -```bash -yarn add @offlegacy/event-tracker -``` - -Using pnpm: - -```bash -pnpm add @offlegacy/event-tracker -``` diff --git a/docs/src/content/ko/_meta.ts b/docs/src/content/ko/_meta.ts index 2a81597..df5ee23 100644 --- a/docs/src/content/ko/_meta.ts +++ b/docs/src/content/ko/_meta.ts @@ -1,6 +1,6 @@ -import { MetaRecord } from "nextra"; +import type { MetaRecord } from "nextra"; -const meta: MetaRecord = { +export default { "getting-started-separator": { type: "separator", title: "시작하기", @@ -12,22 +12,22 @@ const meta: MetaRecord = { layout: "default", }, }, - installation: { - title: "설치", + "why-event-tracker": { + title: "왜 Event Tracker인가요?", theme: { toc: true, layout: "default", }, }, - "quick-start": { - title: "가이드", + installation: { + title: "설치하기", theme: { toc: true, layout: "default", }, }, - "api-separator": { - title: "API", + "api-reference-separator": { + title: "API 레퍼런스", type: "separator", }, "create-tracker": { @@ -38,21 +38,22 @@ const meta: MetaRecord = { }, }, components: { - title: "컴포넌트", + title: "Components", theme: { toc: true, layout: "default", + collapsed: true, }, }, - hook: { - title: "hook", + useTracker: { + title: "useTracker", theme: { toc: true, layout: "default", }, }, "advanced-separator": { - title: "고급", + title: "가이드", type: "separator", }, batching: { @@ -62,6 +63,22 @@ const meta: MetaRecord = { layout: "default", }, }, -}; - -export default meta; + "data-type-validation": { + title: "데이터 타입 검증", + theme: { + toc: true, + layout: "default", + }, + }, + "example-separator": { + title: "예제", + type: "separator", + }, + "basic-example": { + title: "기본", + theme: { + toc: true, + layout: "default", + }, + }, +} satisfies MetaRecord; diff --git a/docs/src/content/ko/quick-start.mdx b/docs/src/content/ko/basic-example.mdx similarity index 100% rename from docs/src/content/ko/quick-start.mdx rename to docs/src/content/ko/basic-example.mdx diff --git a/docs/src/content/ko/create-tracker.mdx b/docs/src/content/ko/create-tracker.mdx index 5b6cbed..8f0dbfe 100644 --- a/docs/src/content/ko/create-tracker.mdx +++ b/docs/src/content/ko/create-tracker.mdx @@ -1,6 +1,6 @@ -# createTracker(config) +# createTracker -원하는 구성으로 트래커 인스턴스를 생성하는 메인 함수입니다. +`createTracker`는 사용자 정의 설정으로 트래커 인스턴스를 생성하는 함수입니다. 이 함수의 파라미터를 통해 이벤트 트래킹을 정의하고, 반환된 튜플을 통해 트래커 인스턴스를 사용할 수 있습니다. ```tsx const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTracker] = createTracker({ @@ -19,95 +19,92 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack }); ``` -### 구성 옵션 +## Reference -#### init +### Parameters -- Type: `(initialContext: Context, setContext: SetContext) => void | Promise` -- 옵셔널 -- 모든 이벤트가 발생하기 전에 실행되는 함수 -- Promise를 반환하면 이벤트가 Promise가 해결될 때까지 지연됩니다. +`createTracker`는 하나의 설정 객체를 인자로 받습니다. -#### send +| 옵션 | 타입 | 설명 | +| ------------ | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | +| `init` | `(initialContext: Context, setContext: SetContext) => void \| Promise` | 모든 이벤트 발생 전에 실행되는 초기화 함수. Promise 지원. | +| `send` | `(params: EventParams \| (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` | 이벤트 전송 함수. Promise 지원. | +| `DOMEvents` | [`DOMEvents`](https://developer.mozilla.org/docs/Web/API/Event) | React DOM 이벤트 핸들러 모음 (`onClick`, `onMouseEnter` 등) | +| `impression` | `ImpressionOptions` | 노출 이벤트 트래킹 설정 | +| `pageView` | `PageViewOptions` | 페이지 뷰 트래킹 설정 | +| `batch` | `BatchConfig` | 이벤트 배칭 설정 | +| `schemas` | `SchemaConfig` | 이벤트 스키마 검증 설정 | -- Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` -- 옵셔널 -- 이벤트를 보내는 표준 함수 -- Promise를 반환하면 이벤트가 Promise가 해결될 때까지 지연됩니다. +--- -#### DOMEvents +#### `init` -- Type: `DOMEvents` -- 옵셔널 -- 표준 React DOM 이벤트 (`onClick`, `onMouseEnter`, 등)의 모음 -- 각 핸들러는 ``에서 해당 이벤트가 발생할 때 실행됩니다. -- 핸들러가 Promise를 반환하면 후속 이벤트 콜백이 해결될 때까지 지연됩니다. +- 타입: `(initialContext: Context, setContext: SetContext) => void | Promise` +- 설명: 모든 이벤트가 발생하기 전, 초기 컨텍스트를 설정하는 함수입니다. 비동기 함수 지원. -#### impression +#### `send` -노출 이벤트를 트래킹하기 위한 설정입니다. +- 타입: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` +- 설명: 이벤트를 외부로 전송하는 함수입니다. 비동기 처리 가능. -- onImpression +#### `DOMEvents` - - Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` - - Optional - - Executed when impression occurs on a `` child - - Promise return value will delay subsequent callbacks +- 타입: `DOMEvents` +- 설명: 표준 React DOM 이벤트 핸들러 객체입니다. `` 컴포넌트에서 사용됩니다. -- options - - Type: `ImpressionOptions` - - 옵셔널 - - 노출 이벤트 트래킹 구성 옵션: - - `threshold`: 노출 필요 비율 (기본값: 0.2) - - `freezeOnceVisible`: 노출 후 교차 상태 고정 (기본값: true) - - `initialIsIntersecting`: 초기 교차 상태 (기본값: false) +#### `impression` -#### pageView +- `impression.onImpression` -페이지 뷰 이벤트를 트래킹하기 위한 설정입니다. + - 타입: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` + - 설명: `` 발생 시 실행되는 콜백 -##### onPageView +- `impression.options` -- Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` -- 옵셔널 -- ``가 마운트될 때 실행됩니다. -- Promise를 반환하면 후속 이벤트가 해결될 때까지 지연됩니다. + - 타입: `ImpressionOptions` + - 속성: -#### batch + - `threshold`: 노출 비율 기준 (기본값: 0.2) + - `freezeOnceVisible`: 노출 후 상태 고정 여부 (기본값: true) + - `initialIsIntersecting`: 초기 교차 여부 (기본값: false) -이벤트 배칭을 위한 설정입니다. +#### `pageView` -- Type: `BatchConfig` -- 옵셔널 -- Properties: - - `enable`: 배칭 활성화 (기본값: false) - - `interval`: 버퍼링 간격 (ms) (기본값: 3000) - - `thresholdSize`: 최대 배칭 크기 (기본값: 25) - - `onFlush`: 배치 비우기 처리 함수 (활성화된 경우 필요) - - `onError`: 오류 처리 함수 (옵셔널) +- `pageView.onPageView` -#### schemas + - 타입: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` + - 설명: `` 마운트 시 실행됩니다. -데이터 타입 검증을 위한 설정입니다. +#### `batch` -- Type: `SchemaConfig` -- 옵셔널 -- Properties: - - `schemas`: [Zod](https://zod.dev/) 스키마의 레코드 - - `onSchemaError`?: 스키마 검증 오류 처리 함수 - - `abortOnError`?: 스키마 검증 오류가 발생한 경우 이벤트 추적 중단 여부 (기본값: false) +- 타입: `BatchConfig` +- 속성: -### Return Value + - `batch.enable`: 배치 활성화 여부 (기본값: false) + - `batch.interval`: 전송 간격(ms, 기본값: 3000) + - `batch.thresholdSize`: 최대 배치 크기 (기본값: 25) + - `batch.onFlush`: 이벤트 전송 처리 함수 + - `batch.onError`: 오류 발생 시 처리 함수 (옵셔널) -`createTracker` 함수는 다음 튜플을 반환합니다: +#### `schemas` -1. 트래킹 컴포넌트를 포함하는 객체: +- 타입: `SchemaConfig` +- 속성: - - [`Provider`](/docs/components) - - [`DOMEvent`](/docs/components/dom-event) - - [`Click`](/docs/components/click) - - [`Impression`](/docs/components/impression) - - [`PageView`](/docs/components/page-view) - - [`SetContext`](/docs/components/set-context) + - `schemas.schema`: [Zod](https://zod.dev/) 기반의 스키마 정의 + - `schemas.onSchemaError`: 스키마 오류 발생 시 처리 함수 + - `schemas.abortOnError`: 오류 시 이벤트 중단 여부 (기본값: false) -2. [커스텀 hook](/docs/hook) +### Returns + +`createTracker`는 다음 두 값을 포함한 튜플을 반환합니다. + +```tsx +const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTracker] = createTracker({...}) +``` + +1. 이벤트 컴포넌트 (`Tracker`) + + - `Provider`, `DOMEvent`, `Click`, `Impression`, `PageView`, `SetContext` + +2. 커스텀 훅 (`useTracker`) diff --git a/docs/src/content/ko/index.mdx b/docs/src/content/ko/index.mdx index 97aed6d..aa96cf6 100644 --- a/docs/src/content/ko/index.mdx +++ b/docs/src/content/ko/index.mdx @@ -1,202 +1,87 @@ -# 소개 - -## `event-tracker`가 필요한 이유 - -이벤트 트래킹은 많은 보일러플레이트 코드와 복잡성을 수반하는 작업입니다. -다음 예시를 살펴보세요. - -```tsx {14,15, 23-30} -// 전통적인 이벤트 트래킹 방식 - -const Page = () => { - const { user, userId } = useUser(); - - return ( -
-

User: {user.name}

- -
- ); -}; - -const Counter = ({ userId }: { userId: string }) => { - // 이벤트 트래킹만을 위해서 'userId'를 prop으로 전달받음 - - const [count, setCount] = useState(0); - const { track } = useTrackEvent(); - - const handleIncrement = () => { - setCount(count + 1); - - track({ - event: "click", - params: { - type: "count", - value: count + 1, - userId, - }, - }); - }; - - return ( -
-

Count: {count}

- -
- ); -}; -``` +import { Steps } from "nextra/components"; -위 코드로 알아본 이벤트 트래킹으로 인한 두 가지 주요 불편사항은 다음과 같습니다: +# 소개 -1. **Prop Drilling**: `userId`가 `` 컴포넌트에서 `` 컴포넌트로 prop으로 전달됩니다. `` 컴포넌트가 컴포넌트 트리 깊숙이 중첩되어 있다면, prop drilling이 더 심각해져 코드의 가독성과 유지보수성이 저하될 수 있습니다. -2. **이벤트 트래킹 로직과 비즈니스 로직의 강결합**: `handleIncrement` 함수는 카운트 증가 로직과 이벤트 트래킹 로직을 모두 포함하고 있습니다. 이벤트 트래킹 로직을 분리하면 코드를 더 깔끔하고 유지보수하기 쉽게 만들 수 있습니다. +Event Tracker 문서에 오신 것을 환영합니다. -## `event-tracker`가 제시하는 새로운 패러다임 +## Event Tracker가 무엇인가요? -`event-tracker`는 이벤트 트래킹을 위한 새로운 패러다임을 소개합니다. -`event-tracker`가 제시하는 선언적 방식은 전통적으로 이벤트 트래킹과 관련된 복잡성을 단순화하여, -모든 개발자들이 쉽게 접근할 수 있도록 합니다. +Event Tracker는 복잡한 이벤트 트래킹 구현 과정을 단순화하고, 개발자가 비즈니스 로직에 더 집중할 수 있도록 돕는 선언적 방식의 React 라이브러리입니다. 모든 규모의 애플리케이션에서 이벤트 트래킹을 쉽고 효율적으로 관리할 수 있도록 설계되었습니다. -### 선언적 이벤트 트래킹 +```tsx +import { createTracker } from "@offlegacy/event-tracker"; -```tsx {5, 10, 24, 26} -const Page = () => { - const { user, userId } = useUser(); +// 트래커 인스턴스 생성 +const [Track, useTracker] = createTracker({ + DOMEvents: { + onClick: (params, context) => { + log("Click event:", params, context); + }, + }, +}); +// 앱에서 사용하기 +function App() { return ( - -
-

User: {user.name}

- -
+ + + + ); -}; - -const Counter = () => { - const [count, setCount] = useState(0); +} +``` - const handleIncrement = () => { - setCount(count + 1); - }; +### 주요 기능 - return ( -
-

Count: {count}

- - - -
- ); -}; -``` +Event Tracker는 개발자 경험과 애플리케이션 성능을 모두 고려한 다양한 기능을 제공합니다. -`event-tracker`를 사용하면 선언적 이벤트 트래킹이 가능해져 코드 가독성이 향상되고 복잡성이 감소합니다. 이는 개발자들이 이벤트 트래킹을 더 쉽게 이해하고 사용할 수 있도록 돕습니다. -이제 `handleIncrement` 함수는 카운트 증가에만 책임이 있고, 이벤트 트래킹은 `` 컴포넌트가 처리합니다. -**이러한 선언적 접근 방식은 개발자가 '어떻게 트래킹할지'가 아닌 '무엇을 트래킹할지'에 집중하도록 합니다.** -어떻게 트래킹할지는 React 앱 외부에서 정의되어야 합니다. +| Feature | Description | +| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 타입 안정성을 갖춘 선언적 API | [TypeScript](https://www.typescriptlang.org/)를 완벽하게 지원하여 개발 과정에서의 오류를 줄이고, 자동 완성을 통해 생산성을 높입니다. | +| 강력한 데이터 타입 검증 | [Zod](https://zod.dev/)를 활용한 스키마 기반 검증으로 데이터의 신뢰성을 확보합니다. | +| 최적화된 성능 | 배칭이나 디바운스, 스로틀링 기능을 통해 네트워크 요청을 최소화하고 애플리케이션 성능에 미치는 영향을 줄입니다. | +| 실행 순서 보장 | 비동기적으로 발생하는 이벤트들에 대해서도 의도한 순서대로 처리되도록 보장합니다. | +| 애널리틱스 도구 독립성 | 특정 애널리틱스 서비스에 종속되지 않고, 원하는 모든 도구([Google Analytics](https://analytics.google.com/), [Amplitude](https://amplitude.com/) 등)와 유연하게 통합할 수 있습니다. | +| 명확한 관심사 분리 | 트래킹 로직과 비즈니스 로직을 효과적으로 분리하여 코드의 유지보수성과 확장성을 극대화합니다. | -### 애플리케이션 외부에서 이벤트 트래킹 응집도 개선 +## 핵심 개념 -```tsx -const [Track] = createTracker({ - DOMEvents: { - onClick: (params, context) => { - log({ - event: "click", - params: { - ...params, - userId: context.userId, - }, - }); - }, - }, - onImpression: (params, context) => { - log({ - event: "impression", - params: { - ...params, - userId: context.userId, - }, - }); - }, -}); -``` +Event Tracker를 효과적으로 사용하기 위해 알아야 할 몇 가지 핵심 개념이 있습니다. -이제 **'어떻게 추적할지'**에 대한 코드가 비즈니스 로직과 분리되었습니다. -애플리케이션 외부에 위치하므로 비즈니스 로직을 변경하지 않고도 이벤트 트래킹 로직을 수정할 수 있습니다. + -### 데이터 타입 검증 +### 인스턴스 (`createTracker`) -`event-tracker`는 [Zod](https://zod.dev/)를 사용하여 스키마 기반으로 데이터 유효성 검증을 제공합니다. +라이브러리의 가장 기본적인 출발점입니다. `createTracker` 함수를 사용하여 트래커 인스턴스(`Track` 컴포넌트 컬렉션과 `useTracker` 훅)를 생성합니다. 이때, DOM 이벤트 핸들러, 노출(Impression) 이벤트 핸들러, 스키마 등을 설정하여 이벤트 트래킹을 정의합니다. -```tsx -import { z } from "zod"; -import { createTracker } from "@offlegacy/event-tracker"; +### 프로바이더 (`Track.Provider`) -interface Context { - // ... -} +React의 Context API를 기반으로 구현되었습니다. 애플리케이션 또는 특정 컴포넌트 트리의 최상단에서 `Track.Provider`로 감싸 하위 컴포넌트들에 트래킹에 필요한 공통 데이터(컨텍스트)를 제공합니다. 예를 들어, `userId`, `pageName` 등의 정보를 컨텍스트로 전달하면, 각 이벤트 트래킹 시 이 정보를 활용할 수 있습니다. -interface Params { - // ... -} +### 이벤트 컴포넌트 (`Track.Click`, `Track.PageView` 등) -// 스키마 정의 -const schemas = { - page_view: z.object({ - title: z.string(), - }), - click_button: z.object({ - target: z.string(), - }), -}; - -// 트래커 설정 -const [Track] = createTracker({ - // 기타 설정... - - schema: { - schemas: { - page_view, - click_button, - }, - onSchemaError: (error) => { - console.error("Schema validation error:", error); - }, - abortOnError: true, - }, -}); +선언적으로 이벤트를 트래킹할 수 있도록 제공되는 특수 컴포넌트들입니다. `createTracker` 리턴 배열의 첫 번째 요소입니다. -// 스키마 사용하기 -; -; -``` +- `Track.Click`: 자식 요소에서 클릭 이벤트가 발생했을 때 트래킹합니다. +- `Track.Impression`: 자식 요소가 화면에 노출되었을 때 트래킹합니다. +- `Track.PageView`: 컴포넌트가 마운트될 때 페이지 뷰 이벤트를 트래킹합니다. -## 주요 기능 +이 외에도 다양한 사용자 인터랙션 및 생명주기 이벤트에 대응하는 컴포넌트를 제공하거나 커스텀하여 사용할 수 있습니다. 각 컴포넌트는 `context`, `params` prop을 통해 해당 이벤트와 관련된 특정 데이터를 전달받고 활용할 수 있습니다. -- 🎯 **타입 안정성을 갖춘 API**: 타입 안전성을 갖춘 선언적 이벤트 트래킹 제공 -- 🛡️ **데이터 타입 검증**: 스키마를 사용한 데이터 타입 안전성과 유효성 보장 -- ⚡️ **최적화된 성능**: 이벤트 배칭을 통한 향상된 성능 -- 🔄 **순서 보장**: 비동기 작업에 대한 실행 순서 보장 -- 🔌 **애널리틱스 도구와의 독립성**: 선택한 모든 애널리틱스 도구와 함께 작동 -- 🧩 **관심사의 분리**: 트래킹 로직과 비즈니스 로직의 분리 유지 -- 📦 **작은 번들 사이즈**: 애플리케이션에 미치는 번들 크기 영향 최소화 +### 커스텀 훅 (`useTracker`) -## 핵심 개념 +컴포넌트의 생명주기나 DOM 이벤트와 직접적으로 관련되지 않은, 보다 복잡하거나 조건부적인 이벤트 트래킹이 필요할 때 사용합니다. `useTracker` 훅을 사용하면 `Track.Provider`로부터 컨텍스트 정보를 가져오고, 정의된 트래킹 로직을 명령형으로 실행할 수 있습니다. -`event-tracker`는 몇 가지 핵심 개념을 기반으로 구축되었습니다: + -1. **Tracker 생성**: `createTracker`를 사용하여 원하는 이벤트 트래킹 지침을 사용하여 트래커 인스턴스를 생성합니다. -2. **Provider**: `Track.Provider`를 사용하여 앱을 래핑하여 컨텍스트를 제공합니다. -3. **이벤트 컴포넌트**: `Track.Click` 또는 `Track.Impression`과 같은 이벤트 컴포넌트를 사용하여 이벤트를 트래킹합니다. -4. **커스텀 Hook**: `useTracker` 훅을 사용하여 명령적으로 트래킹 할 수 있습니다. +## 다음 단계 -다른 섹션에서 각 기능에 대한 자세한 문서를 확인할 수 있습니다: +이러한 핵심 개념들은 서로 유기적으로 작동하여 Event Tracker의 강력하고 유연한 이벤트 트래킹 환경을 구성합니다. 더 자세한 사용법과 각 기능에 대한 심층적인 내용은 아래 문서들에서 확인하실 수 있습니다. -- [createTracker](/docs/create-tracker) - `createTracker`에 대한 자세한 API 문서 -- [components](/docs/components) - 사용 가능한 트래킹 컴포넌트 -- [hook](/docs/hook) - 훅을 사용하여 트래킹 -- [Batching](/docs/batching) - 이벤트 배칭을 통한 성능 최적화 -- [Data Type Validation](/docs/data-type-validation) - 스키마를 사용하여 데이터 타입 안전성과 유효성 보장 +- [왜 Event Tracker인가요?](/docs/why-event-tracker): Event Tracker의 필요성과 주요 기능 소개 +- [`createTracker`](/docs/create-tracker): 트래커 인스턴스 생성 및 상세 설정 가이드 +- [Components](/docs/components): 사용 가능한 모든 트래킹 컴포넌트와 사용 예시 +- [`useTracker`](/docs/hook): 커스텀 훅을 활용한 사용자 지정 트래킹 기법 +- [Batching](/docs/batching): 이벤트 배칭을 통한 성능 최적화 전략 +- [Data Type Validation](/docs/data-type-validation): Zod 스키마를 활용한 데이터 유효성 검증 가이드 diff --git a/docs/src/content/ko/installation.mdx b/docs/src/content/ko/installation.mdx index 87fba1a..fa7b78a 100644 --- a/docs/src/content/ko/installation.mdx +++ b/docs/src/content/ko/installation.mdx @@ -1,19 +1,9 @@ # 설치 -npm을 사용하여 설치하기: +Event Tracker는 React 애플리케이션에서 이벤트 트래킹을 쉽게 구현할 수 있도록 설계된 라이브러리입니다. `React 18.0.0` 이상의 버전에서 사용할 수 있으며, TypeScript를 완벽하게 지원합니다. -```bash -npm install @offlegacy/event-tracker -``` +최신 안정 버전을 설치하려면 아래 명령어를 실행하세요. -yarn을 사용하여 설치하기: - -```bash -yarn add @offlegacy/event-tracker -``` - -pnpm을 사용하여 설치하기: - -```bash -pnpm add @offlegacy/event-tracker +```shell npm2yarn +npm install @offlegacy/event-tracker ``` diff --git a/docs/src/content/ko/hook.mdx b/docs/src/content/ko/useTracker.mdx similarity index 94% rename from docs/src/content/ko/hook.mdx rename to docs/src/content/ko/useTracker.mdx index c775e8f..81385cb 100644 --- a/docs/src/content/ko/hook.mdx +++ b/docs/src/content/ko/useTracker.mdx @@ -1,7 +1,8 @@ -# hook +# useTracker -[`createTracker`](/docs/create-tracker)에서 두 번째 배열 항목으로 반환되는 커스텀 React hook입니다. -이 훅은 컴포넌트 내에서 이벤트 트래킹 기능과 컨텍스트 관리에 접근할 수 있게 합니다. +[`createTracker`](/docs/create-tracker)에서 두 번째 배열 항목으로 반환되는 커스텀 React hook입니다. 이 훅은 컴포넌트 내에서 이벤트 트래킹 기능과 컨텍스트 관리에 접근할 수 있게 합니다. + +예를 들어, 특정 비동기 작업이 완료된 후 또는 사용자의 특정 입력 값에 따라 이벤트를 발생시켜야 할 때 유용합니다. ```tsx import { createTracker } from "@offlegacy/event-tracker"; diff --git a/docs/src/content/ko/why-event-tracker.mdx b/docs/src/content/ko/why-event-tracker.mdx new file mode 100644 index 0000000..83331c5 --- /dev/null +++ b/docs/src/content/ko/why-event-tracker.mdx @@ -0,0 +1,186 @@ +import { Steps } from "nextra/components"; + +# 왜 Event Tracker인가요? + +현대 웹 애플리케이션은 사용자의 행동을 분석하여 서비스 품질을 지속적으로 개선해야 합니다. 그러나 기존의 이벤트 트래킹 방식은 여러 문제점이 나타납니다. + +## Event Tracker가 필요한 이유 + +다음은 전통적인 이벤트 트래킹 방식의 문제점을 보여주는 예시입니다. + +- **Prop Drilling의 고통**: 이벤트 트래킹에 필요한 데이터를 하위 컴포넌트까지 전달하기 위해 수많은 계층을 거쳐 prop을 내려보내야 하는 경우가 많습니다. 이는 코드의 가독성을 해치고 유지보수를 어렵게 만듭니다. +- **로직의 강한 결합**: 비즈니스 로직과 이벤트 트래킹 로직이 한데 섞여 코드의 복잡도를 높이고, 각 로직의 독립적인 테스트와 수정을 어렵게 만듭니다. +- **보일러플레이트 코드 증가**: 반복적인 트래킹 코드 작성은 개발 생산성을 저해하는 요인이 됩니다. + +```tsx {8,15, 24-31} +function Page() { + const { user, userId } = useUser(); // 사용자 정보와 ID를 가져옵니다. + + return ( +
+

User: {user.name}

+ {/* Counter 컴포넌트에 이벤트 트래킹을 위해 userId를 전달합니다. */} + +
+ ); +} + +// 오직 이벤트 트래킹만을 위해서 'userId'를 prop으로 전달받습니다. +// 만약 Counter가 더 깊은 곳에 있다면, prop drilling은 더욱 심해집니다. +function Counter({ userId }: { userId: string }) { + const [count, setCount] = useState(0); + const { track } = useTrackEvent(); // 가상의 트래킹 훅 + + const handleIncrement = () => { + const newCount = count + 1; + setCount(newCount); + + // 비즈니스 로직 (카운트 증가)과 트래킹 로직이 혼재합니다. + track({ + event: "click_increment", + params: { + type: "count", + value: newCount, + userId, // 상위로부터 전달받은 userId 사용 + }, + }); + }; + + return ( +
+

Count: {count}

+ +
+ ); +} +``` + +## Event Tracker가 제시하는 새로운 패러다임 + +Event Tracker는 이벤트 트래킹을 위한 새로운 패러다임을 소개합니다. +Event Tracker가 제시하는 선언적 방식은 전통적으로 이벤트 트래킹과 관련된 복잡성을 단순화하여, 모든 개발자들이 쉽게 접근할 수 있도록 합니다. + + + +### 선언적 이벤트 트래킹 + +```tsx {7, 10, 12, 32, 34} +function Page() { + const { user, userId } = useUser(); + + // Track.Provider를 통해 하위 컴포넌트에 트래킹 컨텍스트(userId)를 제공합니다. + // 더 이상 prop drilling이 필요 없습니다. + return ( + +
+

User: {user.name}

+ {/* userId를 prop으로 전달할 필요가 없습니다. */} +
+
+ ); +} + +function Counter() { + const [count, setCount] = useState(0); + + const handleIncrement = () => { + // 이제 handleIncrement 함수는 순수하게 카운트 증가 로직만 담당합니다. + setCount(count + 1); + }; + + return ( +
+

Count: {count}

+ {/* + Track.Click 컴포넌트가 클릭 이벤트를 감싸고, + 클릭 발생 시 정의된 파라미터와 함께 이벤트를 트래킹합니다. + 컨텍스트로 제공된 userId는 자동으로 트래킹 데이터에 포함됩니다. + */} + + + +
+ ); +} +``` + +Event Tracker를 사용하면 선언적 이벤트 트래킹이 가능해져 코드 가독성이 향상되고 복잡성이 감소합니다. 이는 개발자들이 이벤트 트래킹을 더 쉽게 이해하고 사용할 수 있도록 돕습니다. + +이제 `handleIncrement` 함수는 카운트 증가에만 책임이 있고, 이벤트 트래킹은 `` 컴포넌트가 처리합니다. +**이러한 선언적 접근 방식은 개발자가 '어떻게 트래킹할지'가 아닌 '무엇을 트래킹할지'에 집중하도록 합니다.** +어떻게 트래킹할지는 React 앱 외부에서 정의되어야 합니다. + +### 이벤트 트래킹 응집도 개선 + +```tsx {4-10, 14-20} +const [Track, useTracker] = createTracker({ + // DOM 이벤트 발생 시 실행될 콜백 함수 + DOMEvents: { + onClick: (params, context) => { + // 실제 트래킹 라이브러리(Google Analytics, Amplitude 등) 호출 + logEvent("click_event", { + ...params, // { value: ..., type: "count" } + userId: context.userId, // Provider로부터 받은 userId + }); + }, + // 필요에 따라 onMouseOver, onFocus 등 다양한 DOM 이벤트 핸들러 정의 가능 + }, + // 화면 노출(Impression) 이벤트 발생 시 실행될 콜백 함수 + onImpression: (params, context) => { + logEvent("impression_event", { + ...params, + userId: context.userId, + pagePath: window.location.pathname, + }); + }, +}); +``` + +이제 '어떻게 추적할지'에 대한 코드가 비즈니스 로직과 분리되었습니다. 애플리케이션 외부에 위치하므로 비즈니스 로직을 변경하지 않고도 이벤트 트래킹 로직을 수정할 수 있습니다. + +### 데이터 타입 검증 + +```tsx {13-20, 24-33} +import { z } from "zod"; +import { createTracker } from "@offlegacy/Event Tracker"; + +interface Context { + /* ... */ +} + +interface Params { + /* ... */ +} + +// 스키마 정의 +const schemas = { + page_view: z.object({ + title: z.string(), + }), + click_button: z.object({ + target: z.string(), + }), +}; + +// 트래커 설정 +const [Track] = createTracker({ + schema: { + schemas: { + page_view, + click_button, + }, + onSchemaError: (error) => { + console.error("Schema validation error:", error); + }, + abortOnError: true, + }, +}); + +// 스키마 사용하기 +; +; +``` + +Event Tracker는 선택적으로 [Zod](https://zod.dev/) 라이브러리와 통합하여 스키마 기반의 강력한 데이터 타입 검증 기능을 제공합니다. 이를 통해 개발 단계에서부터 데이터 오류를 방지하고, 트래킹 데이터의 신뢰성을 높일 수 있습니다. + +
From e8b2262e9de17b6a5d743a5020e1939829920c47 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Wed, 4 Jun 2025 04:27:09 +0900 Subject: [PATCH 2/3] docs: update --- docs/src/content/ko/_meta.ts | 2 +- docs/src/content/ko/components/dom-event.mdx | 69 +++++++++++++++---- docs/src/content/ko/components/impression.mdx | 2 +- docs/src/content/ko/components/index.mdx | 17 ++++- docs/src/content/ko/create-tracker.mdx | 39 ++++++++--- docs/src/content/ko/index.mdx | 2 + docs/src/content/ko/installation.mdx | 2 +- .../ko/{useTracker.mdx => use-tracker.mdx} | 0 8 files changed, 104 insertions(+), 29 deletions(-) rename docs/src/content/ko/{useTracker.mdx => use-tracker.mdx} (100%) diff --git a/docs/src/content/ko/_meta.ts b/docs/src/content/ko/_meta.ts index df5ee23..7705f64 100644 --- a/docs/src/content/ko/_meta.ts +++ b/docs/src/content/ko/_meta.ts @@ -45,7 +45,7 @@ export default { collapsed: true, }, }, - useTracker: { + "use-tracker": { title: "useTracker", theme: { toc: true, diff --git a/docs/src/content/ko/components/dom-event.mdx b/docs/src/content/ko/components/dom-event.mdx index fdc0149..1623333 100644 --- a/docs/src/content/ko/components/dom-event.mdx +++ b/docs/src/content/ko/components/dom-event.mdx @@ -1,6 +1,8 @@ +import { Callout } from "nextra/components"; + # DOMEvent -DOM 이벤트를 추적하는 데 사용됩니다. 자식 컴포넌트를 감싸고 지정된 이벤트 핸들러를 실행합니다. +DOM 이벤트를 추적하는 데 사용됩니다. 자식 컴포넌트를 감싸고 지정된 이벤트 핸들러를 실행합니다. `createTracker`의 리턴 배열의 첫 번쨰 요소인 이벤트 컴포넌트 중 하나입니다. ```tsx import { createTracker } from "@offlegacy/event-tracker"; @@ -24,21 +26,64 @@ function App() { } ``` +## Reference + ### Props -- `type: DOMEventNames` - 이벤트 이름 (예: onClick, onFocus) -- 스키마와 함께 사용하는 경우 - - `params: SchemaParams | (context: Context) => SchemaParams` - 스키마 기반 매개변수 - - `schema: string` - 이벤트 매개변수 검증을 위한 스키마 이름 -- 스키마와 함께 사용하지 않는 경우 - - `params: EventParams | (context: Context) => EventParams` - 이벤트 매개변수 -- `enabled?: boolean | ((context: Context, params: EventParams) => boolean)` - 이벤트 추적을 조건부로 활성화/비활성화 (기본값: `true`) -- `debounce?: DebounceConfig` - 연속적인 이벤트 발생을 방지하는 디바운스 설정 -- `throttle?: ThrottleConfig` - 이벤트 발생 빈도를 제한하는 스로틀 설정 +| Props | 타입 | 설명 | 필수 | +| ------------- | ---------------- | ----------------------------------------------------- | ---- | +| DOMEventNames | DOMEventNames | 이벤트 이름 (예: `"onClick"`, `"onFocus"`) | O | +| `enabled` | `boolean | ((context: Context, params: EventParams) => boolean)` | - | +| `debounce` | `DebounceConfig` | 연속적인 이벤트 발생을 방지하는 디바운스 설정 | - | +| `throttle` | `ThrottleConfig` | 이벤트 발생 빈도를 제한하는 스로틀 설정 | - | + +참고: `debounce`와 `throttle`은 상호 배타적이며 함께 사용할 수 없습니다. + +스키마와 함께 사용하는 경우와 아닐 경우 타입이 달라지는 속성이 있습니다. + +| Props | 스키마 여부 | 타입 | 설명 | 필수 | +| -------- | ----------- | ---------------------------------------------------- | --------------------------------------- | ---- | +| `params` | O | `SchemaParams \| (context: Context) => SchemaParams` | 스키마 기반 매개변수 | O | +| `schema` | O | `string` | 이벤트 매개변수 검증을 위한 스키마 이름 | O | +| `params` | - | `EventParams \| (context: Context) => EventParams` | 이벤트 매개변수 | O | + +--- + +#### `params` (필수) + +스키마와 함께 사용하는 경우: + +- 타입: `SchemaParams | (context: Context) => SchemaParams` +- 설명: 스키마 기반 매개변수 + +스키마와 함께 사용하지 않는 경우: + +- 타입: `EventParams | (context: Context) => EventParams` +- 설명: 이벤트 매개변수 + +#### `schema` (필수) + +스키마와 함께 사용하는 경우: + +- 타입: `string` +- 설명: 이벤트 매개변수 검증을 위한 스키마 이름 + +#### `enabled` + +- 타입: `boolean | ((context: Context, params: EventParams) => boolean)` +- 설명: 이벤트 추적을 조건부로 활성화/비활성화 (기본값: `true`) + +#### `debounce` + +- 타입: `DebounceConfig` +- 설명: 연속적인 이벤트 발생을 방지하는 디바운스 설정 + +#### `throttle` -**참고:** `debounce`와 `throttle`은 상호 배타적이며 함께 사용할 수 없습니다. +- 타입: `ThrottleConfig` +- 설명: 이벤트 발생 빈도를 제한하는 스로틀 설정 -### 추적 옵션 예제 +### Examples #### 조건부 추적 diff --git a/docs/src/content/ko/components/impression.mdx b/docs/src/content/ko/components/impression.mdx index d664b5c..7bfbb58 100644 --- a/docs/src/content/ko/components/impression.mdx +++ b/docs/src/content/ko/components/impression.mdx @@ -1,6 +1,6 @@ # Impression -Intersection Observer API를 사용하여 노출 이벤트를 추적합니다. +Intersection Observer API를 사용하여 노출 이벤트를 추적합니다. `createTracker`의 리턴 배열의 첫 번쨰 요소인 이벤트 컴포넌트 중 하나입니다. ```tsx import { createTracker } from "@offlegacy/event-tracker"; diff --git a/docs/src/content/ko/components/index.mdx b/docs/src/content/ko/components/index.mdx index 2189f78..a565b32 100644 --- a/docs/src/content/ko/components/index.mdx +++ b/docs/src/content/ko/components/index.mdx @@ -1,6 +1,6 @@ # Provider -`Provider` 컴포넌트는 애플리케이션에 초기 컨텍스트를 연결하고 제공합니다. +`Provider` 컴포넌트는 애플리케이션에 초기 컨텍스트를 연결하고 제공합니다. `createTracker`의 리턴 배열의 첫 번쨰 요소인 이벤트 컴포넌트 중 하나입니다. ```tsx import { createTracker } from '@offlegacy/event-tracker' @@ -10,12 +10,23 @@ const [Track] = createTracker({...}) function App() { return ( - {/* 애플리케이션 컨텐츠 */} + {/* 애플리케이션 */} ) } ``` +## Reference + ### Props -- `initialContext?: Context` - 초기 컨텍스트 값 +| Props | 타입 | 설명 | 예제 | +| ---------------- | --------- | ---------------- | ------------------- | +| `initialContext` | `Context` | 초기 컨텍스트 값 | `{ userId: '123' }` | + +--- + +#### `initialContext` (필수) + +- 타입: `Context` +- 설명: 초기 컨텍스트 값 diff --git a/docs/src/content/ko/create-tracker.mdx b/docs/src/content/ko/create-tracker.mdx index 8f0dbfe..dea5919 100644 --- a/docs/src/content/ko/create-tracker.mdx +++ b/docs/src/content/ko/create-tracker.mdx @@ -25,7 +25,7 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack `createTracker`는 하나의 설정 객체를 인자로 받습니다. -| 옵션 | 타입 | 설명 | +| 설정 | 타입 | 설명 | | ------------ | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | | `init` | `(initialContext: Context, setContext: SetContext) => void \| Promise` | 모든 이벤트 발생 전에 실행되는 초기화 함수. Promise 지원. | | `send` | `(params: EventParams \| (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` | 이벤트 전송 함수. Promise 지원. | @@ -64,9 +64,9 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack - 타입: `ImpressionOptions` - 속성: - - `threshold`: 노출 비율 기준 (기본값: 0.2) - - `freezeOnceVisible`: 노출 후 상태 고정 여부 (기본값: true) - - `initialIsIntersecting`: 초기 교차 여부 (기본값: false) + - `threshold`: 노출 비율 기준 (기본값: `0.2`) + - `freezeOnceVisible`: 노출 후 상태 고정 여부 (기본값: `true`) + - `initialIsIntersecting`: 초기 교차 여부 (기본값: `false`) #### `pageView` @@ -80,9 +80,9 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack - 타입: `BatchConfig` - 속성: - - `batch.enable`: 배치 활성화 여부 (기본값: false) - - `batch.interval`: 전송 간격(ms, 기본값: 3000) - - `batch.thresholdSize`: 최대 배치 크기 (기본값: 25) + - `batch.enable`: 배치 활성화 여부 (기본값: `false`) + - `batch.interval`: 전송 간격(ms, 기본값: `3000`) + - `batch.thresholdSize`: 최대 배치 크기 (기본값: `25`) - `batch.onFlush`: 이벤트 전송 처리 함수 - `batch.onError`: 오류 발생 시 처리 함수 (옵셔널) @@ -93,7 +93,7 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack - `schemas.schema`: [Zod](https://zod.dev/) 기반의 스키마 정의 - `schemas.onSchemaError`: 스키마 오류 발생 시 처리 함수 - - `schemas.abortOnError`: 오류 시 이벤트 중단 여부 (기본값: false) + - `schemas.abortOnError`: 오류 시 이벤트 중단 여부 (기본값: `false`) ### Returns @@ -103,8 +103,25 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTracker] = createTracker({...}) ``` -1. 이벤트 컴포넌트 (`Tracker`) +#### [Components](./components) - - `Provider`, `DOMEvent`, `Click`, `Impression`, `PageView`, `SetContext` +리턴 배열에서 첫 요소인 이벤트 컴포넌트는 여러 가지 이벤트 컴포넌트를 포함하고 있습니다. -2. 커스텀 훅 (`useTracker`) +```tsx +const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }] = createTracker(config); +``` + +- `Provider` +- `DOMEvent` +- `Click` +- `Impression` +- `PageView` +- `SetContext` + +#### [useTracker](./use-tracker) + +```tsx +const [, useTracker] = createTracker(config); +``` + +리턴 배열에서 두번째 요소인 커스텀 React hook입니다. 이 훅은 컴포넌트 내에서 이벤트 트래킹 기능과 컨텍스트 관리에 접근할 수 있게 합니다. diff --git a/docs/src/content/ko/index.mdx b/docs/src/content/ko/index.mdx index aa96cf6..03c0269 100644 --- a/docs/src/content/ko/index.mdx +++ b/docs/src/content/ko/index.mdx @@ -55,6 +55,8 @@ Event Tracker를 효과적으로 사용하기 위해 알아야 할 몇 가지 라이브러리의 가장 기본적인 출발점입니다. `createTracker` 함수를 사용하여 트래커 인스턴스(`Track` 컴포넌트 컬렉션과 `useTracker` 훅)를 생성합니다. 이때, DOM 이벤트 핸들러, 노출(Impression) 이벤트 핸들러, 스키마 등을 설정하여 이벤트 트래킹을 정의합니다. +목적에 따라 구분하여 여러 가지 트래커 인스턴스를 생성할 수 있습니다. (예를 들어, Google Analytics로 보내는 이벤트와 Amplitude로 보내는 이벤트를 구분하여 생성할 수 있습니다.) + ### 프로바이더 (`Track.Provider`) React의 Context API를 기반으로 구현되었습니다. 애플리케이션 또는 특정 컴포넌트 트리의 최상단에서 `Track.Provider`로 감싸 하위 컴포넌트들에 트래킹에 필요한 공통 데이터(컨텍스트)를 제공합니다. 예를 들어, `userId`, `pageName` 등의 정보를 컨텍스트로 전달하면, 각 이벤트 트래킹 시 이 정보를 활용할 수 있습니다. diff --git a/docs/src/content/ko/installation.mdx b/docs/src/content/ko/installation.mdx index fa7b78a..9a3705c 100644 --- a/docs/src/content/ko/installation.mdx +++ b/docs/src/content/ko/installation.mdx @@ -1,6 +1,6 @@ # 설치 -Event Tracker는 React 애플리케이션에서 이벤트 트래킹을 쉽게 구현할 수 있도록 설계된 라이브러리입니다. `React 18.0.0` 이상의 버전에서 사용할 수 있으며, TypeScript를 완벽하게 지원합니다. +Event Tracker는 React 애플리케이션에서 이벤트 트래킹을 쉽게 구현할 수 있도록 설계된 라이브러리입니다. `React 18.0.0` 이상의 버전에서 사용할 수 있습니다. 최신 안정 버전을 설치하려면 아래 명령어를 실행하세요. diff --git a/docs/src/content/ko/useTracker.mdx b/docs/src/content/ko/use-tracker.mdx similarity index 100% rename from docs/src/content/ko/useTracker.mdx rename to docs/src/content/ko/use-tracker.mdx From b8da2691e1aa73b0c0411103386b498ea663ea56 Mon Sep 17 00:00:00 2001 From: gwansikk Date: Thu, 12 Jun 2025 20:20:57 +0900 Subject: [PATCH 3/3] docs: update en --- docs/src/content/en/_meta.ts | 42 +++- .../en/{quick-start.mdx => basic-example.mdx} | 6 +- docs/src/content/en/components.mdx | 189 --------------- docs/src/content/en/components/index.mdx | 17 +- docs/src/content/en/create-tracker.mdx | 136 ++++++----- docs/src/content/en/hook.mdx | 223 ----------------- docs/src/content/en/index.mdx | 229 +++++------------- docs/src/content/en/installation.mdx | 4 +- docs/src/content/en/use-tracker.mdx | 225 +++++++++++++++++ docs/src/content/en/why-event-tracker.mdx | 184 ++++++++++++++ 10 files changed, 591 insertions(+), 664 deletions(-) rename docs/src/content/en/{quick-start.mdx => basic-example.mdx} (83%) delete mode 100644 docs/src/content/en/components.mdx delete mode 100644 docs/src/content/en/hook.mdx create mode 100644 docs/src/content/en/use-tracker.mdx create mode 100644 docs/src/content/en/why-event-tracker.mdx diff --git a/docs/src/content/en/_meta.ts b/docs/src/content/en/_meta.ts index 29d0799..1c36a1e 100644 --- a/docs/src/content/en/_meta.ts +++ b/docs/src/content/en/_meta.ts @@ -1,6 +1,6 @@ import { MetaRecord } from "nextra"; -const meta: MetaRecord = { +export default { "getting-started-separator": { type: "separator", title: "Getting Started", @@ -12,21 +12,21 @@ const meta: MetaRecord = { layout: "default", }, }, - installation: { - title: "Installation", + "why-event-tracker": { + title: "Why Event Tracker?", theme: { toc: true, layout: "default", }, }, - "quick-start": { - title: "Quick Start", + installation: { + title: "Installation", theme: { toc: true, layout: "default", }, }, - "api-separator": { + "api-reference-separator": { title: "API Reference", type: "separator", }, @@ -38,21 +38,21 @@ const meta: MetaRecord = { }, }, components: { - title: "components", + title: "Components", theme: { toc: true, layout: "default", }, }, - hook: { - title: "hook", + "use-tracker": { + title: "useTracker", theme: { toc: true, layout: "default", }, }, "advanced-separator": { - title: "Advanced", + title: "Guides", type: "separator", }, batching: { @@ -62,6 +62,22 @@ const meta: MetaRecord = { layout: "default", }, }, -}; - -export default meta; + "data-type-validation": { + title: "Data Type Validation", + theme: { + toc: true, + layout: "default", + }, + }, + "example-separator": { + title: "Examples", + type: "separator", + }, + "basic-example": { + title: "Basic", + theme: { + toc: true, + layout: "default", + }, + }, +} satisfies MetaRecord; diff --git a/docs/src/content/en/quick-start.mdx b/docs/src/content/en/basic-example.mdx similarity index 83% rename from docs/src/content/en/quick-start.mdx rename to docs/src/content/en/basic-example.mdx index 0a5728b..6c06e3e 100644 --- a/docs/src/content/en/quick-start.mdx +++ b/docs/src/content/en/basic-example.mdx @@ -1,6 +1,6 @@ -# Quick Start +# Guide -Here's a simple example of how to use event-tracker: +Here's a simple example demonstrating how to use `event-tracker`: ```tsx import { createTracker } from "@offlegacy/event-tracker"; @@ -14,7 +14,7 @@ const [Track, useTracker] = createTracker({ }, }); -// Use in your app +// Usage within the app function App() { return ( diff --git a/docs/src/content/en/components.mdx b/docs/src/content/en/components.mdx deleted file mode 100644 index 64113ec..0000000 --- a/docs/src/content/en/components.mdx +++ /dev/null @@ -1,189 +0,0 @@ -# Components - -event-tracker provides several components for tracking different types of events. Each component is designed to be easy to use while maintaining type safety and performance. - -## Provider - -The `Provider` component connects and provides initial context to your application. - -```tsx -import { createTracker } from '@offlegacy/event-tracker' - -const [Track] = createTracker({...}) - -function App() { - return ( - - {/* Your app content */} - - ) -} -``` - -### Props - -- `initialContext: unknown` - Initial context value - -## DOMEvent - -Used for tracking DOM events. Wraps a child component and fires the specified event handler. - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track] = createTracker({ - DOMEvents: { - onFocus: (params, context) => { - // Handle focus event - }, - }, -}); - -function App() { - return ( - - - - - - ); -} -``` - -### Props - -- `type: DOMEventNames` - Event name (e.g., onClick, onFocus) -- (With schema) - - `params: SchemaParams | (context: Context) => SchemaParams` - Event parameters - - `schema?: string` - A name of schema that will be used to validate the event parameters -- (Without schema) - - `params: EventParams | (context: Context) => EventParams` - Event parameters - -## Click - -A specialized version of `DOMEvent` for click events (`type="onClick"`). - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track] = createTracker({ - DOMEvents: { - onClick: (params, context) => { - // Handle click event - }, - }, -}); - -function App() { - return ( - - - - - - ); -} -``` - -### Props - -- With schema - - `params: SchemaParams | (context: Context) => SchemaParams` - Click event parameters - - `schema?: string` - A name of schema that will be used to validate the event parameters -- Without schema - - `params: EventParams | (context: Context) => EventParams` - Click event parameters - -## Impression - -Tracks impression events using the Intersection Observer API. - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track] = createTracker({ - impression: { - onImpression: (params, context) => { - // Handle impression event - }, - options: { - threshold: 0.5, - }, - }, -}); - -function App() { - return ( - - -
Tracked content
-
-
- ); -} -``` - -### Props - -- Without schema - - `params: EventParams | (context: Context) => EventParams` - Impression event parameters - - `options?: ImpressionOptions` - Optional configuration (overrides global options) -- With schema - - `params: SchemaParams | (context: Context) => SchemaParams` - Impression event parameters - - `schema?: string` - A name of schema that will be used to validate the event parameters - - `options?: ImpressionOptions` - Optional configuration (overrides global options) - -## PageView - -Tracks page view events on component mount. - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track] = createTracker({ - pageView: { - onPageView: (params, context) => { - // Handle page view event - }, - }, -}); - -function App() { - return ( - - - - ); -} -``` - -### Props - -- With schema - - `params: SchemaParams | (context: Context) => SchemaParams` - Page view event parameters - - `schema?: string` - A name of schema that will be used to validate the event parameters -- Without schema - - `params: EventParams | (context: Context) => EventParams` - Page view event parameters - -## SetContext - -Sets or updates the tracking context. - -```tsx -import { createTracker } from '@offlegacy/event-tracker' - -const [Track] = createTracker({...}) - -function App() { - return ( - - - - ) -} -``` - -### Props - -- `context: unknown | ((prevContext: unknown) => unknown)` - New context value or update function diff --git a/docs/src/content/en/components/index.mdx b/docs/src/content/en/components/index.mdx index 814a375..13da1ae 100644 --- a/docs/src/content/en/components/index.mdx +++ b/docs/src/content/en/components/index.mdx @@ -1,6 +1,6 @@ # Provider -The `Provider` component connects and provides initial context to your application. +The `Provider` component attaches and provides the initial context to your application. It is one of the event components included as the first element of the tuple returned by `createTracker`. ```tsx import { createTracker } from '@offlegacy/event-tracker' @@ -10,12 +10,23 @@ const [Track] = createTracker({...}) function App() { return ( - {/* Your app content */} + {/* Application */} ) } ``` +## Reference + ### Props -- `initialContext?: Context` - Initial context value +| Props | Type | Description | Example | +| ---------------- | --------- | --------------------- | ------------------- | +| `initialContext` | `Context` | Initial context value | `{ userId: '123' }` | + +--- + +#### `initialContext` (required) + +- Type: `Context` +- Description: The initial context value provided to the application. diff --git a/docs/src/content/en/create-tracker.mdx b/docs/src/content/en/create-tracker.mdx index 229279b..6d143a0 100644 --- a/docs/src/content/en/create-tracker.mdx +++ b/docs/src/content/en/create-tracker.mdx @@ -1,6 +1,6 @@ -# createTracker(config) +# createTracker -The main function to create a tracker instance with your desired configuration. +`createTracker` is a function used to create tracker instances with custom configurations. It allows you to define event tracking behaviors through parameters, returning a tuple containing the tracker instance and a custom hook for usage. ```tsx const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTracker] = createTracker({ @@ -19,95 +19,109 @@ const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTrack }); ``` -### Configuration Options +## Reference -#### init +### Parameters + +`createTracker` accepts a single configuration object as its parameter. + +| Option | Type | Description | +| ------------ | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| `init` | `(initialContext: Context, setContext: SetContext) => void \| Promise` | Initialization function executed before any event occurs. Supports async operations. | +| `send` | `(params: EventParams \| (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` | Function for sending events externally. Supports async operations. | +| `DOMEvents` | [`DOMEvents`](https://developer.mozilla.org/docs/Web/API/Event) | Collection of React DOM event handlers (`onClick`, `onMouseEnter`, etc.). | +| `impression` | `ImpressionOptions` | Configuration for impression event tracking. | +| `pageView` | `PageViewOptions` | Configuration for page view tracking. | +| `batch` | `BatchConfig` | Configuration for event batching. | +| `schemas` | `SchemaConfig` | Configuration for event schema validation. | + +--- + +#### `init` - Type: `(initialContext: Context, setContext: SetContext) => void | Promise` -- Optional -- Function executed before any events happen -- If it returns a promise, events will be delayed until the promise resolves +- Description: Function to set the initial context before any event occurs. Supports asynchronous functions. -#### send +#### `send` - Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` -- Optional -- Standard function to send events -- If it returns a promise, events will be delayed until the promise resolves +- Description: Function for sending events externally. Supports asynchronous operations. -#### DOMEvents +#### `DOMEvents` - Type: `DOMEvents` -- Optional -- Collection of standard React DOM events (`onClick`, `onMouseEnter`, etc.) -- Each handler is executed when that event occurs on a `` -- If a handler returns a promise, subsequent event callbacks will be delayed until it resolves - -#### impression +- Description: Standard React DOM event handlers. Used by `` components. -Configuration for impression tracking: +#### `impression` -- onImpression +- `impression.onImpression` - Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` - - Optional - - Executed when impression occurs on a `` child - - Promise return value will delay subsequent callbacks + - Description: Callback executed when `` event occurs. -- options - - Type: `ImpressionOptions` - - Optional - - Configuration options for impression tracking: - - `threshold`: Percentage of visibility needed (default: 0.2) - - `freezeOnceVisible`: Freeze intersection state after visibility (default: true) - - `initialIsIntersecting`: Initial intersection state (default: false) +- `impression.options` -#### pageView + - Type: `ImpressionOptions` + - Properties: -Configuration for page view tracking: + - `threshold`: Visibility threshold ratio (default: `0.2`) + - `freezeOnceVisible`: Fix visibility state after impression (default: `true`) + - `initialIsIntersecting`: Initial intersection state (default: `false`) -##### onPageView +#### `pageView` -- Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` -- Optional -- Executed when `` is mounted -- Promise return value will delay subsequent events +- `pageView.onPageView` -#### batch + - Type: `(params: EventParams | (context: Context) => EventParams, context: Context, setContext: SetContext) => TaskReturnType` + - Description: Executed when `` component mounts. -Configuration for event batching: +#### `batch` - Type: `BatchConfig` -- Optional - Properties: - - `enable`: Enable batching (default: false) - - `interval`: Flush interval in ms (default: 3000) - - `thresholdSize`: Max batch size (default: 25) - - `onFlush`: Function to handle batch flush (required if enabled) - - `onError`: Error handler (optional) -#### schemas + - `batch.enable`: Enable batching (default: `false`) + - `batch.interval`: Sending interval in milliseconds (default: `3000`) + - `batch.thresholdSize`: Maximum batch size (default: `25`) + - `batch.onFlush`: Function to handle batched event sending + - `batch.onError`: Optional error handling function -Configuration for data type validation: +#### `schemas` - Type: `SchemaConfig` -- Optional - Properties: - - `schemas`: A record of [Zod](https://zod.dev/) schemas - - `onSchemaError`?: Function to handle schema validation errors - - `abortOnError`?: Whether to abort event tracking if a schema validation error occurs (default: false) -### Return Value + - `schemas.schema`: Schema definitions based on [Zod](https://zod.dev/) + - `schemas.onSchemaError`: Function executed when schema validation errors occur + - `schemas.abortOnError`: Abort events on validation error (default: `false`) -The `createTracker` function returns a tuple containing: +### Returns -1. An object with tracking components: +`createTracker` returns a tuple containing the following two elements: - - [`Provider`](/docs/components) - - [`DOMEvent`](/docs/components/dom-event) - - [`Click`](/docs/components/click) - - [`Impression`](/docs/components/impression) - - [`PageView`](/docs/components/page-view) - - [`SetContext`](/docs/components/set-context) +```tsx +const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }, useTracker] = createTracker({...}) +``` + +#### [Components](./components) + +The first element of the returned tuple contains various event components: + +```tsx +const [{ Provider, DOMEvent, Click, Impression, PageView, SetContext }] = createTracker(config); +``` + +- `Provider` +- `DOMEvent` +- `Click` +- `Impression` +- `PageView` +- `SetContext` + +#### [useTracker](./use-tracker) + +```tsx +const [, useTracker] = createTracker(config); +``` -2. The [custom hook](/docs/hook) +The second element of the returned tuple is a custom React hook. It provides access to event tracking functionalities and context management within components. diff --git a/docs/src/content/en/hook.mdx b/docs/src/content/en/hook.mdx deleted file mode 100644 index 0c8c4e2..0000000 --- a/docs/src/content/en/hook.mdx +++ /dev/null @@ -1,223 +0,0 @@ -# hook - -A custom React hook returned as the second array item from [`createTracker`](/docs/create-tracker). -It provides access to tracking functionality and context management within your components. - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track, useTracker] = createTracker({...}) - -function MyComponent() { - const { setContext, getContext, track, trackWithSchema } = useTracker(); - - return ( - // Your component content - ); -} -``` - -### Return Value - -The hook returns an object with the following properties: - -#### setContext - -- Type: `(context: Context) => void` -- Sets or updates the current tracking context -- Can be used to update user information, session data, etc. - -```tsx -const { setContext } = useTracker(); - -// Set new context -setContext({ userId: "user-123" }); - -// Update context based on previous value -setContext((prev) => ({ - ...prev, - lastActive: new Date(), -})); -``` - -#### getContext - -- Type: `() => Context` -- Returns the current tracking context -- Useful for accessing current tracking state - -```tsx -const { getContext } = useTracker(); - -const currentContext = getContext(); -console.log("Current user:", currentContext.userId); -``` - -#### track - -- Type: `Record void>` -- Object containing all configured event tracking functions -- Keys match the event names defined in your tracker configuration -- Accepts optional `TrackingOptions` for advanced control - -```tsx -const { track } = useTracker(); - -// Track a simple click event -track.onClick({ buttonId: "submit" }); - -// Track with conditional logic -track.onClick( - { buttonId: "premium" }, - { - enabled: (context) => context.user?.isPremium, - }, -); - -// Track with debouncing -track.onClick( - { buttonId: "search" }, - { - debounce: { delay: 300, leading: false, trailing: true }, - }, -); - -// Track with throttling -track.onClick( - { buttonId: "rapid-action" }, - { - throttle: { delay: 1000, leading: true, trailing: false }, - }, -); - -// Track an impression -track.onImpression({ elementId: "hero" }); -``` - -#### trackWithSchema - -- Type: `Record void>` -- Object containing all configured event tracking functions with schema validation -- Keys match the event names defined in your tracker configuration -- Accepts optional `TrackingOptions` for advanced control - -```tsx -const { trackWithSchema } = useTracker(); - -// Track a click event with schema -trackWithSchema.onClick({ schema: "click", params: { buttonId: "submit" } }); - -// Track with conditional logic and schema -trackWithSchema.onClick( - { - schema: "premium_click", - params: { buttonId: "premium", userId: "123" }, - }, - { - enabled: (context, params) => context.user?.id === params.userId, - }, -); - -// Track with throttling and schema -trackWithSchema.onImpression( - { - schema: "impression", - params: { elementId: "hero", userId: "123" }, - }, - { - throttle: { delay: 2000, leading: true, trailing: false }, - }, -); -``` - -### TrackingOptions - -Both `track` and `trackWithSchema` methods accept an optional second parameter with the following options: - -- `enabled?: boolean | ((context: Context, params: EventParams) => boolean)` - Conditionally enable/disable event tracking -- `debounce?: DebounceConfig` - Debounce configuration to prevent rapid successive events -- `throttle?: ThrottleConfig` - Throttle configuration to limit event frequency - -**Note:** `debounce` and `throttle` are mutually exclusive and cannot be used together. - -#### DebounceConfig - -```tsx -interface DebounceConfig { - delay: number; // Delay in milliseconds - leading?: boolean; // Execute on leading edge (default: false) - trailing?: boolean; // Execute on trailing edge (default: true) -} -``` - -#### ThrottleConfig - -```tsx -interface ThrottleConfig { - delay: number; // Delay in milliseconds - leading?: boolean; // Execute on leading edge (default: true) - trailing?: boolean; // Execute on trailing edge (default: false) -} -``` - -### Example Usage - -Here's a complete example showing how to use the custom hook: - -```tsx -import { createTracker } from "@offlegacy/event-tracker"; - -const [Track, useTracker] = createTracker({ - onClick: (params) => { - // Send event to analytics service - analytics.track(params); - }, - pageView: { - onPageView: (params) => { - // Send event to analytics service - analytics.pageView(params); - }, - }, -}); - -function UserProfile({ userId }) { - const { setContext, track, trackWithSchema } = useTracker(); - - useEffect(() => { - // Update context when user ID changes - setContext({ userId }); - - // Track page view - track.onPageView({ page: "profile" }); - }, [userId]); - - const handleSettingsClick = () => { - // Track custom event - trackWithSchema.onClick({ schema: "settings", params: { userId } }); - }; - - return ( -
-

User Profile

- -
- ); -} -``` - -### Best Practices - -1. **Context Updates** - - - Use `setContext` for global state that affects multiple events - - Consider using the function form of `setContext` for updates based on previous state - -2. **Event Tracking** - - - Use the specific event functions from `track` or `trackWithSchema` when possible - -3. **Performance** - - Avoid calling tracking functions in render - - Use callbacks or effects for tracking - - Consider using [batching](/docs/batching) for better performance - - Consider using [data type validation](/docs/data-type-validation) for data type safety diff --git a/docs/src/content/en/index.mdx b/docs/src/content/en/index.mdx index 2a87bb1..c2585a0 100644 --- a/docs/src/content/en/index.mdx +++ b/docs/src/content/en/index.mdx @@ -1,202 +1,89 @@ -# Introduction - -## Motivation - -Event tracking is a complex task that requires a lot of boilerplate code and complexity. -Take a look at this example. - -```tsx {14,15, 23-30} -// Traditional event tracking - -const Page = () => { - const { user, userId } = useUser(); - - return ( -
-

User: {user.name}

- -
- ); -}; - -const Counter = ({ userId }: { userId: string }) => { - // Receives 'userId' as a prop just for event tracking purposes. - - const [count, setCount] = useState(0); - const { track } = useTrackEvent(); - - const handleIncrement = () => { - setCount(count + 1); - - track({ - event: "click", - params: { - type: "count", - value: count + 1, - userId, - }, - }); - }; +import { Steps } from "nextra/components"; - return ( -
-

Count: {count}

- -
- ); -}; -``` - -The two main inconveniences caused by event tracking in the code are: +# Introduction -1. **Prop Drilling**: The `userId` is passed as a prop to the `` component from the `` component. If the `` component is nested deeper within the component tree, prop drilling can become more severe, reducing the readability and maintainability of the code. -2. **Coupling of Event Tracking Logic and Business Logic**: The `handleIncrement` function contains both the logic for incrementing the count and tracking the event. Separating the event tracking logic can make the code cleaner and easier to maintain. +Welcome to the Event Tracker documentation. -## The New Paradigm +## What is Event Tracker? -`event-tracker` introduces a new paradigm for event tracking. -The declarative nature of this paradigm simplifies -the complexity traditionally associated with event tracking, making it accessible to developers of all skill levels. +Event Tracker is a declarative React library designed to simplify the implementation of complex event tracking, allowing developers to focus more on their business logic. It is designed to efficiently manage event tracking in applications of any scale. -### Declarative event tracking +```tsx +import { createTracker } from "@offlegacy/event-tracker"; -```tsx {5, 10, 24, 26} -const Page = () => { - const { user, userId } = useUser(); +// Creating a tracker instance +const [Track, useTracker] = createTracker({ + DOMEvents: { + onClick: (params, context) => { + log("Click event:", params, context); + }, + }, +}); +// Usage within an app +function App() { return ( - -
-

User: {user.name}

- -
+ + + + ); -}; +} +``` -const Counter = () => { - const [count, setCount] = useState(0); +### Key Features - const handleIncrement = () => { - setCount(count + 1); - }; +Event Tracker provides various features prioritizing both developer experience and application performance. - return ( -
-

Count: {count}

- - - -
- ); -}; -``` +| Feature | Description | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Declarative API with Type Safety | Fully supports [TypeScript](https://www.typescriptlang.org/), reducing errors during development and increasing productivity through auto-completion. | +| Powerful Data Type Validation | Ensures data reliability through schema-based validation using [Zod](https://zod.dev/). | +| Optimized Performance | Minimizes network requests through batching, debouncing, or throttling, reducing the impact on application performance. | +| Guaranteed Execution Order | Ensures asynchronous events are processed in the intended sequence. | +| Analytics Tool Independence | Flexible integration with any analytics tool (e.g., [Google Analytics](https://analytics.google.com/), [Amplitude](https://amplitude.com/)), without being tied to any specific provider. | +| Clear Separation of Concerns | Effectively separates tracking logic from business logic, maximizing code maintainability and scalability. | -Using `event-tracker` allows for declarative event tracking, which improves code readability and reduces complexity. This helps developers understand and use event tracking more easily. -Your `handleIncrement` function is now only responsible for incrementing the count, and the event tracking is handled by the `` component. -**This declarative approach makes the developer focus on _'what to track'_ and not _'how to track'._** -How to track should be defined outside of the React app. +## Core Concepts -### Improve code cohesion outside your application. +There are several key concepts you need to understand to use Event Tracker effectively. -```tsx -const [Track] = createTracker({ - DOMEvents: { - onClick: (params, context) => { - log({ - event: "click", - params: { - ...params, - userId: context.userId, - }, - }); - }, - }, - onImpression: (params, context) => { - log({ - event: "impression", - params: { - ...params, - userId: context.userId, - }, - }); - }, -}); -``` + -Your instructions for **'how to track'** is now separated from your business logic. -It's located outside your application, so you can change your event tracking provider without having to change your application code. +### Instance (`createTracker`) -### Data Type Validation +The foundational starting point of the library. Use the `createTracker` function to generate a tracker instance (a collection of `Track` components and the `useTracker` hook). Define event tracking by configuring DOM event handlers, impression event handlers, schemas, and more. -`event-tracker` provides built-in schema validation using [Zod](https://zod.dev/), a TypeScript-first schema validation library. +Multiple tracker instances can be created according to specific purposes (e.g., separate instances for sending events to Google Analytics and Amplitude). -```tsx -import { z } from "zod"; -import { createTracker } from "@offlegacy/event-tracker"; +### Provider (`Track.Provider`) -interface Context { - // ... -} +Implemented using React's Context API. Wrap your application or component tree at the top with `Track.Provider` to provide common tracking data (context) to child components. For example, providing information such as `userId` and `pageName` through context allows utilizing this information during each event tracking. -interface Params { - // ... -} +### Event Components (`Track.Click`, `Track.PageView`, etc.) -// Define Schemas -const schemas = { - page_view: z.object({ - title: z.string(), - }), - click_button: z.object({ - target: z.string(), - }), -}; - -// Configure Tracker -const [Track] = createTracker({ - // other configurations... - - schema: { - schemas: { - page_view, - click_button, - }, - onSchemaError: (error) => { - console.error("Schema validation error:", error); - }, - abortOnError: true, - }, -}); +Special components provided to track events declaratively. These are available from the first element of the array returned by `createTracker`. -// Use the schemas -; -; -``` +- `Track.Click`: Tracks click events occurring on child elements. +- `Track.Impression`: Tracks when child elements become visible on the screen. +- `Track.PageView`: Tracks page view events upon component mount. -## Key Features +In addition, you can customize or utilize various provided components that respond to different user interactions and lifecycle events. Each component can receive and utilize specific event-related data through the `context` and `params` props. -- 🎯 **Type-safe APIs**: Declarative event tracking with complete type safety -- 🛡️ **Data Type Validation**: Ensures data type safety and consistency using schemas -- ⚡️ **Optimized Performance**: Enhanced performance through event batching -- 🔄 **Guaranteed Order**: Guaranteed execution order for async operations -- 🔌 **Analytics Agnostic**: Works with any analytics provider of your choice -- 🧩 **Clean Separation**: Keeps tracking logic separate from business logic -- 📦 **Lightweight**: Minimal bundle size impact on your application +### Custom Hook (`useTracker`) -## Basic Concepts +Used for more complex or conditional event tracking unrelated directly to component lifecycles or DOM events. The `useTracker` hook lets you access context information from `Track.Provider` and execute defined tracking logic imperatively. -`event-tracker` is built around a few core concepts: + -1. **Tracker Creation**: Use `createTracker` to create a tracker instance with your desired event tracking instructions. -2. **Provider**: Wrap your app with `Track.Provider` to provide context. -3. **Event Components**: Use components like `Track.Click` or `Track.Impression` to track events. -4. **Hooks**: Use the `useTracker` hook to access tracking functionality in your components imperatively. +## Next Steps -Check out the other sections for detailed documentation on each feature: +These core concepts work synergistically to provide Event Tracker's powerful and flexible event-tracking environment. For detailed usage and in-depth information about each feature, refer to the documents below: -- [createTracker](/docs/create-tracker) - Detailed API documentation on `createTracker` -- [components](/docs/components) - Available tracking components -- [hook](/docs/hook) - Track using the hook -- [Batching](/docs/batching) - Optimizing performance with event batching -- [Data Type Validation](/docs/data-type-validation) - Ensuring data type safety and consistency using schemas +- [Why Event Tracker?](/docs/why-event-tracker): Introduction to the necessity and core features of Event Tracker. +- [`createTracker`](/docs/create-tracker): Guide to creating tracker instances and detailed configurations. +- [Components](/docs/components): Examples and details of all available tracking components. +- [`useTracker`](/docs/hook): Custom tracking techniques using the custom hook. +- [Batching](/docs/batching): Strategies for optimizing performance through event batching. +- [Data Type Validation](/docs/data-type-validation): Guide to data validation using Zod schemas. diff --git a/docs/src/content/en/installation.mdx b/docs/src/content/en/installation.mdx index 4d9af8e..2cba716 100644 --- a/docs/src/content/en/installation.mdx +++ b/docs/src/content/en/installation.mdx @@ -1,6 +1,8 @@ # Installation -Using npm: +Event Tracker is a library designed to simplify event tracking in React applications. It supports versions `React 18.0.0` and higher. + +To install the latest stable version, run the following command: ```shell npm2yarn npm install @offlegacy/event-tracker diff --git a/docs/src/content/en/use-tracker.mdx b/docs/src/content/en/use-tracker.mdx new file mode 100644 index 0000000..81385cb --- /dev/null +++ b/docs/src/content/en/use-tracker.mdx @@ -0,0 +1,225 @@ +# useTracker + +[`createTracker`](/docs/create-tracker)에서 두 번째 배열 항목으로 반환되는 커스텀 React hook입니다. 이 훅은 컴포넌트 내에서 이벤트 트래킹 기능과 컨텍스트 관리에 접근할 수 있게 합니다. + +예를 들어, 특정 비동기 작업이 완료된 후 또는 사용자의 특정 입력 값에 따라 이벤트를 발생시켜야 할 때 유용합니다. + +```tsx +import { createTracker } from "@offlegacy/event-tracker"; + +const [Track, useTracker] = createTracker({...}) + +function MyComponent() { + const { setContext, getContext, track, trackWithSchema } = useTracker(); + + return ( + // 컴포넌트 내용 + ); +} +``` + +### 반환 값 + +이 hook은 다음 속성을 포함하는 객체를 반환합니다: + +#### setContext + +- Type: `(context: Context) => void` +- 현재 트래킹 컨텍스트를 설정하거나 업데이트합니다. +- 사용자 정보, 세션 데이터 등을 업데이트하는 데 사용할 수 있습니다. + +```tsx +const { setContext } = useTracker(); + +// 새로운 컨텍스트 설정 +setContext({ userId: "user-123" }); + +// 이전 값에 기반한 컨텍스트 업데이트 +setContext((prev) => ({ + ...prev, + lastActive: new Date(), +})); +``` + +#### getContext + +- Type: `() => Context` +- 현재 트래킹 컨텍스트를 반환합니다. +- 현재 트래킹 상태에 접근하는 데 유용합니다. + +```tsx +const { getContext } = useTracker(); + +const currentContext = getContext(); +console.log("Current user:", currentContext.userId); +``` + +#### track + +- Type: `Record void>` +- 모든 구성된 이벤트 트래킹 함수를 포함하는 객체 +- key는 트래커 구성에 정의된 이벤트 이름과 일치합니다. +- 고급 제어를 위한 선택적 `TrackingOptions`를 허용합니다. + +```tsx +const { track } = useTracker(); + +// 간단한 클릭 이벤트 추적 +track.onClick({ buttonId: "submit" }); + +// 조건부 로직과 함께 추적 +track.onClick( + { buttonId: "premium" }, + { + enabled: (context) => context.user?.isPremium, + }, +); + +// 디바운싱과 함께 추적 +track.onClick( + { buttonId: "search" }, + { + debounce: { delay: 300, leading: false, trailing: true }, + }, +); + +// 스로틀링과 함께 추적 +track.onClick( + { buttonId: "rapid-action" }, + { + throttle: { delay: 1000, leading: true, trailing: false }, + }, +); + +// 노출 이벤트 추적 +track.onImpression({ elementId: "hero" }); +``` + +#### trackWithSchema + +- Type: `Record void>` +- 스키마 검증이 포함된 모든 구성된 이벤트 트래킹 함수를 포함하는 객체 +- key는 트래커 구성에 정의된 이벤트 이름과 일치합니다. +- 고급 제어를 위한 선택적 `TrackingOptions`를 허용합니다. + +```tsx +const { trackWithSchema } = useTracker(); + +// 스키마와 함께 클릭 이벤트 추적 +trackWithSchema.onClick({ schema: "click", params: { buttonId: "submit" } }); + +// 조건부 로직과 스키마와 함께 추적 +trackWithSchema.onClick( + { + schema: "premium_click", + params: { buttonId: "premium", userId: "123" }, + }, + { + enabled: (context, params) => context.user?.id === params.userId, + }, +); + +// 스로틀링과 스키마와 함께 추적 +trackWithSchema.onImpression( + { + schema: "impression", + params: { elementId: "hero", userId: "123" }, + }, + { + throttle: { delay: 2000, leading: true, trailing: false }, + }, +); +``` + +### TrackingOptions + +`track`과 `trackWithSchema` 메서드 모두 다음 옵션을 포함하는 선택적 두 번째 매개변수를 허용합니다: + +- `enabled?: boolean | ((context: Context, params: EventParams) => boolean)` - 이벤트 추적을 조건부로 활성화/비활성화 +- `debounce?: DebounceConfig` - 연속적인 이벤트 발생을 방지하는 디바운스 설정 +- `throttle?: ThrottleConfig` - 이벤트 발생 빈도를 제한하는 스로틀 설정 + +**참고:** `debounce`와 `throttle`은 상호 배타적이며 함께 사용할 수 없습니다. + +#### DebounceConfig + +```tsx +interface DebounceConfig { + delay: number; // 밀리초 단위의 지연 시간 + leading?: boolean; // 선행 에지에서 실행 (기본값: false) + trailing?: boolean; // 후행 에지에서 실행 (기본값: true) +} +``` + +#### ThrottleConfig + +```tsx +interface ThrottleConfig { + delay: number; // 밀리초 단위의 지연 시간 + leading?: boolean; // 선행 에지에서 실행 (기본값: true) + trailing?: boolean; // 후행 에지에서 실행 (기본값: false) +} +``` + +### 사용 예제 + +다음은 이 hook을 사용하는 예제입니다: + +```tsx +import { createTracker } from "@offlegacy/event-tracker"; + +const [Track, useTracker] = createTracker({ + onClick: (params) => { + // 이벤트를 애널리틱스 서비스로 전송 + analytics.track(params); + }, + pageView: { + onPageView: (params) => { + // Send event to analytics service + analytics.pageView(params); + }, + }, +}); + +function UserProfile({ userId }) { + const { setContext, track, trackWithSchema } = useTracker(); + + useEffect(() => { + // 사용자 ID가 변경될 때 컨텍스트 업데이트 + setContext({ userId }); + + // 페이지 뷰 이벤트 트래킹 + track.onPageView({ page: "profile" }); + }, [userId]); + + const handleSettingsClick = () => { + // 사용자 설정 이벤트 트래킹 + trackWithSchema.onClick({ schema: "settings", params: { userId } }); + }; + + return ( +
+

User Profile

+ +
+ ); +} +``` + +### Best Practices + +1. **컨텍스트 업데이트** + + - 여러 이벤트에 영향을 주는 전역 상태를 업데이트하기 위해 `setContext`를 사용하세요. + - 이전 상태에 기반한 업데이트를 위해 `setContext`의 함수 형태를 고려하세요. + +2. **이벤트 트래킹** + + - 가능한 경우 `track` 또는 `trackWithSchema`에서 이벤트 함수를 사용하세요. + +3. **성능** + + - 렌더링 중에 이벤트 트래킹 함수를 호출하지 마세요. + - 콜백 또는 효과를 사용하세요. + - [배칭](/docs/batching)을 사용하여 성능을 향상시키세요. + - [데이터 타입 검증](/docs/data-type-validation)을 사용하여 데이터 타입 안전성을 확인하세요. diff --git a/docs/src/content/en/why-event-tracker.mdx b/docs/src/content/en/why-event-tracker.mdx new file mode 100644 index 0000000..96f9050 --- /dev/null +++ b/docs/src/content/en/why-event-tracker.mdx @@ -0,0 +1,184 @@ +import { Steps } from "nextra/components"; + +# Why Event Tracker? + +Modern web applications need to continuously analyze user behavior to improve service quality. However, traditional event tracking approaches have various issues. + +## Why is Event Tracker Necessary? + +The following example illustrates common problems with traditional event tracking methods: + +- **Pain of Prop Drilling**: Often, tracking data must be passed through multiple layers of components, negatively impacting readability and maintainability. +- **Strong Coupling of Logic**: Mixing business logic and tracking logic increases complexity and makes it harder to independently test and modify each. +- **Increased Boilerplate Code**: Repetitive tracking code significantly hampers developer productivity. + +```tsx {8,15,24-31} +function Page() { + const { user, userId } = useUser(); // Retrieves user information and ID. + + return ( +
+

User: {user.name}

+ {/* Passes userId to Counter component solely for event tracking purposes */} + +
+ ); +} + +// Receives 'userId' as prop exclusively for event tracking. +// Prop drilling intensifies if Counter is placed even deeper in the tree. +function Counter({ userId }: { userId: string }) { + const [count, setCount] = useState(0); + const { track } = useTrackEvent(); // Hypothetical tracking hook + + const handleIncrement = () => { + const newCount = count + 1; + setCount(newCount); + + // Mixing business logic (incrementing count) with tracking logic. + track({ + event: "click_increment", + params: { + type: "count", + value: newCount, + userId, // userId received from the parent component + }, + }); + }; + + return ( +
+

Count: {count}

+ +
+ ); +} +``` + +## New Paradigm Offered by Event Tracker + +Event Tracker introduces a new paradigm for event tracking. Its declarative approach simplifies traditional complexities, making event tracking accessible for all developers. + + + +### Declarative Event Tracking + +```tsx {7,10,12,32,34} +function Page() { + const { user, userId } = useUser(); + + // Provides tracking context (userId) to child components via Track.Provider. + // Eliminates the need for prop drilling. + return ( + +
+

User: {user.name}

+ {/* No need to pass userId as prop */} +
+
+ ); +} + +function Counter() { + const [count, setCount] = useState(0); + + const handleIncrement = () => { + // handleIncrement now focuses solely on increment logic. + setCount(count + 1); + }; + + return ( +
+

Count: {count}

+ {/* + Track.Click component wraps the click event and automatically tracks the event + with the provided parameters. The userId provided in the context is automatically included. + */} + + + +
+ ); +} +``` + +With Event Tracker, declarative event tracking significantly improves code readability and reduces complexity, helping developers more easily understand and implement tracking. + +Now the `handleIncrement` function is only responsible for increasing the count, while the `` component handles tracking. +**This declarative approach lets developers focus on 'what to track' rather than 'how to track.'** +The actual tracking logic is defined externally from the React app. + +### Improved Cohesion in Event Tracking + +```tsx {4-10,14-20} +const [Track, useTracker] = createTracker({ + // Callback executed on DOM events + DOMEvents: { + onClick: (params, context) => { + // Call the actual tracking library (e.g., Google Analytics, Amplitude) + logEvent("click_event", { + ...params, // { value: ..., type: "count" } + userId: context.userId, // userId from Track.Provider + }); + }, + // Define additional DOM event handlers (onMouseOver, onFocus, etc.) as needed + }, + // Callback executed on Impression events + onImpression: (params, context) => { + logEvent("impression_event", { + ...params, + userId: context.userId, + pagePath: window.location.pathname, + }); + }, +}); +``` + +Now the code for **'how to track'** is separated from business logic. Located externally, it can be modified without impacting business logic. + +### Data Type Validation + +```tsx {13-20,24-33} +import { z } from "zod"; +import { createTracker } from "@offlegacy/event-tracker"; + +interface Context { + /* ... */ +} + +interface Params { + /* ... */ +} + +// Schema definition +const schemas = { + page_view: z.object({ + title: z.string(), + }), + click_button: z.object({ + target: z.string(), + }), +}; + +// Tracker setup +const [Track] = createTracker({ + schema: { + schemas: { + page_view, + click_button, + }, + onSchemaError: (error) => { + console.error("Schema validation error:", error); + }, + abortOnError: true, + }, +}); + +// Using schemas +; +; +``` + +Event Tracker optionally integrates with [Zod](https://zod.dev/) to offer robust schema-based data validation. This ensures data correctness from the development stage, enhancing tracking data reliability. + +