{"id":30778114,"url":"https://github.com/0xdeafcafe/react-contextual-analytics","last_synced_at":"2026-04-17T02:31:27.771Z","repository":{"id":297076662,"uuid":"986843446","full_name":"0xdeafcafe/react-contextual-analytics","owner":"0xdeafcafe","description":"React Contextual Analytics is an context-driven approach to blah blah","archived":false,"fork":false,"pushed_at":"2025-10-15T19:29:18.000Z","size":281,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-22T05:35:45.540Z","etag":null,"topics":["analytics","analytics-framework","analytics-tracking","developer-exp","react","react-context"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xdeafcafe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-20T07:50:11.000Z","updated_at":"2025-10-15T19:29:22.000Z","dependencies_parsed_at":"2025-06-04T03:21:01.694Z","dependency_job_id":"e3820045-7c77-4037-877c-1125e0a9d4a8","html_url":"https://github.com/0xdeafcafe/react-contextual-analytics","commit_stats":null,"previous_names":["0xdeafcafe/react-contextual-analytics"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/0xdeafcafe/react-contextual-analytics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xdeafcafe%2Freact-contextual-analytics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xdeafcafe%2Freact-contextual-analytics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xdeafcafe%2Freact-contextual-analytics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xdeafcafe%2Freact-contextual-analytics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xdeafcafe","download_url":"https://codeload.github.com/0xdeafcafe/react-contextual-analytics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xdeafcafe%2Freact-contextual-analytics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31912330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","analytics-framework","analytics-tracking","developer-exp","react","react-context"],"created_at":"2025-09-05T05:52:18.326Z","updated_at":"2026-04-17T02:31:27.761Z","avatar_url":"https://github.com/0xdeafcafe.png","language":"TypeScript","readme":"# react-contextual-analytics\n\n[![npm version](https://badge.fury.io/js/react-contextual-analytics.svg)](https://badge.fury.io/js/react-contextual-analytics)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](https://www.typescriptlang.org/)\n[![React](https://img.shields.io/badge/React-18+-61dafb.svg)](https://reactjs.org/)\n[![Bundle Size](https://img.shields.io/bundlephobia/minzip/react-contextual-analytics)](https://bundlephobia.com/package/react-contextual-analytics)\n[![Build Status](https://github.com/0xdeafcafe/react-contextual-analytics/workflows/ci/badge.svg)](https://github.com/0xdeafcafe/react-contextual-analytics/actions)\n[![Coverage](https://img.shields.io/codecov/c/github/0xdeafcafe/react-contextual-analytics)](https://codecov.io/gh/0xdeafcafe/react-contextual-analytics)\n\nA React framework for collecting and emitting analytics events with minimal boilerplate. Automatically collects context through component boundaries, making analytics implementation simpler and more maintainable.\n\n## Quick Start\n\n```bash\n# Install\nnpm install react-contextual-analytics\n# or\nyarn add react-contextual-analytics\n# or\npnpm add react-contextual-analytics\n```\n\n```jsx\n// 1. Create your analytics client\nimport { \n\tcreateAnalyticsClient, \n\tAnalyticsProvider, \n\tAnalyticsBoundary \n} from 'react-contextual-analytics';\nimport { console, google } from 'react-contextual-analytics/providers';\n\nconst analyticsClient = createAnalyticsClient([\n\tconsole, // For development logging\n\tgoogle,  // For Google Analytics\n]);\n\n// 2. Wrap your app\nfunction App() {\n\treturn (\n\t\t\u003cAnalyticsProvider client={analyticsClient}\u003e\n\t\t\t\u003cYourApp /\u003e\n\t\t\u003c/AnalyticsProvider\u003e\n\t);\n}\n\n// 3. Start collecting analytics\nfunction ProductPage({ product }) {\n\treturn (\n\t\t\u003cAnalyticsBoundary \n\t\t\tname=\"product-page\"\n\t\t\tattributes={{ productId: product.id }}\n\t\t\tsendViewedEvent={true}\n\t\t\u003e\n\t\t\t{(emitter) =\u003e (\n\t\t\t\t\u003cbutton onClick={() =\u003e emit('clicked', 'add-to-cart')}\u003e\n\t\t\t\t\tAdd to Cart\n\t\t\t\t\u003c/button\u003e\n\t\t\t)}\n\t\t\u003c/AnalyticsBoundary\u003e\n\t);\n}\n```\n\n## Key Concepts\n\n### 1. Context Collection\n- Wrap components with `AnalyticsBoundary` to define context\n- Context is automatically inherited from parent boundaries\n- Events include all relevant context from their location in the tree\n\n```jsx\nimport { AnalyticsBoundary } from 'react-contextual-analytics';\n\nfunction StorePage() {\n\treturn (\n\t\t\u003cAnalyticsBoundary name=\"store\" attributes={{ storeId: \"123\" }}\u003e\n\t\t\t\u003cAnalyticsBoundary name=\"product\" attributes={{ productId: \"456\" }}\u003e\n\t\t\t\t{(emitter) =\u003e (\n\t\t\t\t\t\u003cbutton onClick={() =\u003e emit('clicked', 'view-details')}\u003e\n\t\t\t\t\t\tView Product\n\t\t\t\t\t\u003c/button\u003e\n\t\t\t\t)}\n\t\t\t\u003c/AnalyticsBoundary\u003e\n\t\t\u003c/AnalyticsBoundary\u003e\n\t);\n}\n// Event includes: { \n//   boundary: \"store.product\", \n//   context: { storeId: \"123\", productId: \"456\" } \n// }\n```\n\n### 2. Event Emission\nTwo ways to emit events:\n\n1. **Using Boundary Callback** (recommended for multiple events):\n```jsx\nimport { AnalyticsBoundary } from 'react-contextual-analytics';\n\nfunction CheckoutForm() {\n\treturn (\n\t\t\u003cAnalyticsBoundary name=\"checkout\" attributes={{ step: 'payment' }}\u003e\n\t\t\t{(emitter) =\u003e (\n\t\t\t\t\u003cdiv\u003e\n\t\t\t\t\t\u003cbutton onClick={() =\u003e emit('clicked', 'purchase', {\n\t\t\t\t\t\tamount: 99.99,\n\t\t\t\t\t\tproductId: '123'\n\t\t\t\t\t})}\u003e\n\t\t\t\t\t\tBuy Now\n\t\t\t\t\t\u003c/button\u003e\n\t\t\t\t\t\u003cbutton onClick={() =\u003e emit('clicked', 'cancel')}\u003e\n\t\t\t\t\t\tCancel\n\t\t\t\t\t\u003c/button\u003e\n\t\t\t\t\u003c/div\u003e\n\t\t\t)}\n\t\t\u003c/AnalyticsBoundary\u003e\n\t);\n}\n```\n\n2. **Using Hook** (for single events):\n```jsx\nimport { useAnalytics } from 'react-contextual-analytics';\n\nfunction AddToCartButton({ productId }) {\n\tconst { emit } = useAnalytics();\n\t\n\treturn (\n\t\t\u003cbutton \n\t\t\tonClick={() =\u003e emit('clicked', 'add-to-cart', { productId })}\n\t\t\u003e\n\t\t\tAdd to Cart\n\t\t\u003c/button\u003e\n\t);\n}\n```\n\n### 3. Event Structure\n```typescript\ninterface Event {\n\taction: string;      // e.g., 'clicked', 'viewed'\n\tname?: string;       // e.g., 'add-to-cart', 'purchase'\n\tboundary?: string;   // e.g., 'store.product'\n\tattributes?: object; // Event-specific data\n\tcontext?: {          // Automatically collected\n\t\thref: string;\n\t\twindowWidth: number;\n\t\t// ... other global context\n\t};\n}\n```\n\n## Best Practices\n\n1. **Boundary Organization**\n\t- Place boundaries around logical sections (pages, features, forms)\n\t- Keep hierarchy shallow (2-3 levels)\n\t- Use meaningful names\n\n2. **Context Management**\n\t- Define context at highest relevant level\n\t- Use consistent attribute names\n\t- Avoid context duplication\n\n3. **Event Naming**\n\t- Use consistent actions: 'clicked', 'viewed', 'submitted'\n\t- Make names descriptive but concise\n\t- Follow consistent patterns\n\n## Custom Providers\n\nCreate custom providers by implementing the Provider interface:\n\n```typescript\ninterface Provider {\n\tid: string;\n\tsend: (event: Event) =\u003e Promise\u003cvoid\u003e;\n\tsetup?: () =\u003e void;\n}\n\n// Example: Sentry Provider\nconst sentryProvider = {\n\tid: 'sentry',\n\tsend: (event) =\u003e {\n\t\tcaptureBreadcrumb({\n\t\t\tmessage: [event.boundary, event.name, event.action].filter(Boolean).join(' '),\n\t\t\tlevel: 'info',\n\t\t});\n\t}\n};\n```\n\n## API Reference\n\n- `AnalyticsProvider`: Root provider component\n- `AnalyticsBoundary`: Context boundary component\n- `useAnalytics`: Hook for emitting events\n- `createAnalyticsClient`: Create analytics client with providers\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xdeafcafe%2Freact-contextual-analytics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xdeafcafe%2Freact-contextual-analytics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xdeafcafe%2Freact-contextual-analytics/lists"}