npm package: @powerlimit/analytics
Description: Simple, privacy-friendly analytics library with anonymous user tracking, location data, and IP capture
Author: Ivan Bondar
Latest version: 1.3.3

# @ivanbondar/analytics

Simple, privacy-friendly analytics library with anonymous user tracking, location data (timezone & language), and server-side IP capture support.

## Features

✅ **Anonymous User Tracking** - UUID-based identification stored in cookies  
✅ **Location Context** - Automatic timezone and language collection (no permissions needed)  
✅ **Privacy-First** - No annoying GPS permission prompts  
✅ **React Components** - Built-in AnalyticsProvider for auto page tracking  
✅ **Server-Side Helpers** - IP extraction and payload enrichment utilities  
✅ **Type-Safe** - Full TypeScript support  
✅ **Framework Agnostic** - Core works with any JavaScript framework  
✅ **Lightweight** - Minimal dependencies (uuid + js-cookie)  

## Installation

```bash
npm install @ivanbondar/analytics uuid js-cookie
```

```bash
yarn add @ivanbondar/analytics uuid js-cookie
```

```bash
pnpm add @ivanbondar/analytics uuid js-cookie
```

## Quick Start

```typescript
import { Analytics } from '@ivanbondar/analytics';

// Create analytics instance
const analytics = new Analytics({
  apiUrl: '/api/analytics', // Your analytics endpoint
  cookieName: 'anonymous_user_id', // Optional, default: 'anonymous_user_id'
  cookieExpireDays: 365, // Optional, default: 365
});

// Track events
analytics.track('button_click', { button: 'subscribe' });

// Track page views
analytics.trackPageView('/about');

// Track clicks
analytics.trackClick('cta-button', { section: 'hero' });

// Track actions
analytics.trackAction('form_submit', 'contact', { success: true });

// Get anonymous user ID
const userId = analytics.getAnonymousId();

// Reset anonymous ID (logout, privacy)
analytics.resetAnonymousId();
```

## What Gets Tracked

Every event automatically includes:

```json
{
  "eventName": "page_view",
  "userUuid": "550e8400-e29b-41d4-a716-446655440000",
  "host": "example.com",
  "url": "/about",
  "properties": "{\"page\":\"/about\"}",
  "location": "{\"timezone\":\"America/New_York\",\"language\":\"en-US\"}"
}
```

### Automatic Data Collection

| Data | Description | Permission Required |
|------|-------------|---------------------|
| `userUuid` | Anonymous user identifier (UUID v4) | Cookie consent |
| `eventName` | Name of the event | None |
| `host` | Website hostname | None |
| `url` | Current page URL | None |
| `properties` | Custom event properties (JSON) | None |
| `location.timezone` | User's timezone (e.g., "America/New_York") | None |
| `location.language` | Browser language (e.g., "en-US") | None |

## API Reference

### `new Analytics(config)`

Creates a new analytics instance.

**Config:**
```typescript
{
  apiUrl: string;              // Required: Your analytics API endpoint
  cookieName?: string;         // Optional: Cookie name (default: 'anonymous_user_id')
  cookieExpireDays?: number;   // Optional: Cookie expiration (default: 365 days)
}
```

### `track(eventName, properties?)`

Tracks a custom event.

```typescript
analytics.track('video_play', {
  videoId: '123',
  title: 'Demo Video',
  duration: 120
});
```

### `trackPageView(page, properties?)`

Tracks a page view.

```typescript
analytics.trackPageView('/about', {
  referrer: document.referrer,
  section: 'company'
});
```

### `trackClick(element, properties?)`

Tracks a click event.

```typescript
analytics.trackClick('signup-button', {
  location: 'hero',
  variant: 'primary'
});
```

### `trackAction(action, category?, properties?)`

Tracks a user action with optional category.

```typescript
analytics.trackAction('form_submit', 'contact', {
  formId: 'contact-form',
  success: true,
  fields: 3
});
```

### `getAnonymousId()`

Returns the current anonymous user ID.

```typescript
const userId = analytics.getAnonymousId();
// "550e8400-e29b-41d4-a716-446655440000"
```

### `resetAnonymousId()`

Resets the anonymous user ID (creates a new one).

```typescript
// Useful for logout or privacy purposes
analytics.resetAnonymousId();
```

## Framework Examples

### React / Next.js (App Router)

**1. Create analytics instance:**

```typescript
// lib/analytics.ts
import { Analytics } from '@ivanbondar/analytics';

export const analytics = new Analytics({
  apiUrl: process.env.NEXT_PUBLIC_ANALYTICS_API_URL || '/api/analytics',
  cookieName: 'anonymous_user_id',
  cookieExpireDays: 365,
});
```

**2. Add AnalyticsProvider for auto page tracking:**

```typescript
// components/AnalyticsProvider.tsx
'use client';

import { usePathname } from 'next/navigation';
import { AnalyticsProvider as BaseAnalyticsProvider } from '@ivanbondar/analytics/react';
import { analytics } from '@/lib/analytics';

export function AnalyticsProvider() {
  const pathname = usePathname();
  return <BaseAnalyticsProvider analytics={analytics} pathname={pathname} />;
}
```

**3. Add to root layout:**

```typescript
// app/layout.tsx
import { AnalyticsProvider } from '@/components/AnalyticsProvider';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <AnalyticsProvider />
        {children}
      </body>
    </html>
  );
}
```

**4. Create API route for IP tracking:**

```typescript
// app/api/analytics/route.ts
import { createAnalyticsHandler } from '@ivanbondar/analytics/server';

export const POST = createAnalyticsHandler({
  apiUrl: process.env.ANALYTICS_API_URL!,
  anonymizeIp: false, // Set to true for GDPR compliance
  includeUserAgent: true,
});
```

**5. Use in components:**

```typescript
import { analytics } from '@/lib/analytics';

function MyComponent() {
  const handleClick = () => {
    analytics.trackClick('button', { label: 'Get Started' });
  };

  return <button onClick={handleClick}>Get Started</button>;
}
```

### Vue.js

```typescript
// plugins/analytics.ts
import { Analytics } from '@ivanbondar/analytics';

export const analytics = new Analytics({
  apiUrl: import.meta.env.VITE_ANALYTICS_API_URL,
});

// main.ts
import { analytics } from './plugins/analytics';
app.config.globalProperties.$analytics = analytics;

// Usage in components
<script setup>
import { analytics } from '@/plugins/analytics';

const handleClick = () => {
  analytics.trackClick('button', { label: 'Submit' });
};
</script>
```

### Vanilla JavaScript

```html
<script type="module">
  import { Analytics } from '@ivanbondar/analytics';

  const analytics = new Analytics({
    apiUrl: '/api/analytics'
  });

  // Track page view
  analytics.trackPageView(window.location.pathname);

  // Track button clicks
  document.querySelectorAll('[data-track]').forEach(button => {
    button.addEventListener('click', () => {
      analytics.trackClick(button.dataset.track);
    });
  });
</script>
```

## React Components (`@ivanbondar/analytics/react`)

### AnalyticsProvider

Automatic page view tracking for React/Next.js:

```typescript
import { AnalyticsProvider } from '@ivanbondar/analytics/react';
import { usePathname } from 'next/navigation'; // Next.js App Router
import { analytics } from './analytics-instance';

function MyAnalyticsProvider() {
  const pathname = usePathname();
  
  return (
    <AnalyticsProvider 
      analytics={analytics} 
      pathname={pathname}
      properties={{ customProp: 'value' }} // Optional
    />
  );
}
```

### useAnalyticsPageView Hook

Manual page view tracking:

```typescript
import { useAnalyticsPageView } from '@ivanbondar/analytics/react';
import { analytics } from './analytics-instance';

function MyComponent() {
  useAnalyticsPageView(analytics, '/custom-page', {
    section: 'dashboard',
    user: 'premium'
  });
  
  return <div>Content</div>;
}
```

## Server-Side Utilities (`@ivanbondar/analytics/server`)

### createAnalyticsHandler

Create a complete API route handler with IP tracking:

```typescript
// app/api/analytics/route.ts (Next.js App Router)
import { createAnalyticsHandler } from '@ivanbondar/analytics/server';

export const POST = createAnalyticsHandler({
  apiUrl: process.env.ANALYTICS_API_URL!,
  anonymizeIp: false,        // Set to true for GDPR compliance
  includeUserAgent: true,     // Include user agent in payload
  onError: (error) => {       // Optional error handler
    console.error('Analytics error:', error);
  },
});
```

### getClientIp

Extract client IP from request headers (handles CDNs, proxies):

```typescript
import { getClientIp } from '@ivanbondar/analytics/server';
import { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const ip = getClientIp(request.headers);
  console.log('Client IP:', ip);
}
```

### enrichAnalyticsPayload

Enrich payload with server-side data:

```typescript
import { enrichAnalyticsPayload } from '@ivanbondar/analytics/server';
import { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const body = await request.json();
  
  const enriched = enrichAnalyticsPayload(body, request.headers, {
    anonymizeIp: true,
    includeUserAgent: true,
  });
  
  // enriched now includes: ipAddress, userAgent, serverTimestamp
}
```

### anonymizeIp

Anonymize IP addresses for GDPR compliance:

```typescript
import { anonymizeIp } from '@ivanbondar/analytics/server';

anonymizeIp('192.168.1.123')  // Returns: '192.168.1.0'
anonymizeIp('2001:db8::1')    // Returns: '2001:db8::0'
```

### isBot

Filter out bot traffic:

```typescript
import { isBot } from '@ivanbondar/analytics/server';

const userAgent = request.headers.get('user-agent');
if (isBot(userAgent)) {
  return Response.json({ success: true, ignored: true });
}
```

**Environment Variables:**
```bash
# .env.local
NEXT_PUBLIC_ANALYTICS_API_URL=/api/analytics
ANALYTICS_API_URL=https://your-analytics-api.com/track
```

## Privacy & GDPR

### Data Collected

- **Anonymous UUID**: Stored in cookie, no personal information
- **Timezone**: Browser timezone (e.g., "America/New_York")
- **Language**: Browser language preference (e.g., "en-US")
- **IP Address**: Only if using server-side proxy (server-side only)
- **User Agent**: Only if using server-side proxy (server-side only)

### GDPR Compliance

1. **Disclose in Privacy Policy**
   - Anonymous user tracking (UUID)
   - Timezone and language collection
   - IP address collection (if applicable)
   - Cookie usage and expiration

2. **Cookie Consent**
   - Include analytics cookies in consent banner
   - Allow users to opt-out

3. **User Rights**
   - Provide data export by UUID
   - Allow deletion requests
   - Provide `resetAnonymousId()` for user control

4. **IP Anonymization** (Optional)
   ```typescript
   // In your server-side proxy
   function anonymizeIp(ip: string): string {
     const parts = ip.split('.');
     parts[3] = '0';
     return parts.join('.');
   }
   ```

## TypeScript Support

Full TypeScript support with exported types:

```typescript
import { 
  Analytics, 
  AnalyticsConfig, 
  LocationData, 
  TrackEventPayload 
} from '@ivanbondar/analytics';

const config: AnalyticsConfig = {
  apiUrl: '/api/analytics',
  cookieName: 'user_id',
  cookieExpireDays: 90,
};

const analytics = new Analytics(config);
```

## Browser Support

- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Opera 76+

Requires:
- `Intl.DateTimeFormat` API (timezone detection)
- `navigator.language` (language detection)
- `fetch` API
- ES2020+ features

## Dependencies

- `uuid` - UUID v4 generation
- `js-cookie` - Cookie management

## License

MIT

## Author

Ivan Bondar

## Contributing

Contributions welcome! Please open an issue or PR.

## Support

For issues and questions, please open an issue on GitHub.