npm package: @sensorswave/wechat-mini
Description: Data collection and A/B testing SDK for Mini Program
Author: Sensors Wave
Latest version: 0.1.2

# WeChat Mini Program SDK

[Sensors Wave](http://sensorswave.com/) WeChat Mini Program is a data collection and A/B testing library for mini programs.

If you're new to Sensors Wave, check out our product and create an account at [sensorswave.com](http://sensorswave.com/).

## SDK Usage

### 1. Install via npm

```bash
npm install @sensorswave/wechat-mini
```

### 2. Import and Initialize

```javascript
// app.js
import Sensorswave from '@sensorswave/wechat-mini';

Sensorswave.init('your-source-token', {
  apiHost: 'https://your-api-host.com',
  autoCapture: true,
  batchSend: true,
  enableAB: false,
  debug: false
});
```

### 3. Send Custom Events

```javascript
Sensorswave.trackEvent('ButtonClick', {
  button_name: 'submit',
  page: 'home'
});
```

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiHost | string | (required) | API host address for sending events |
| autoCapture | boolean | true | Whether to automatically capture mini-program lifecycle events |
| batchSend | boolean | true | Whether to use batch sending (sends events in batches) |
| enableAB | boolean | false | Whether to enable A/B testing feature |
| enableClickTrack | boolean | false | Whether to enable automatic click tracking on elements |
| debug | boolean | false | Whether to enable debug mode for logging |

## API Methods

### Event Tracking

#### trackEvent

Manually track a custom event with properties.

**Parameters:**
- `eventName` (string, required): The name of the event to track
- `properties` (Object, optional): Additional properties to include with the event

**Example:**
```javascript
Sensorswave.trackEvent('ViewProduct', {
  product_id: '12345',
  product_name: 'iPhone 15',
  category: 'electronics',
  price: 799
});
```

#### track

Advanced tracking method with full control over event data. Allows you to specify the complete event object including time, trace ID, user properties, and more.

**Parameters:**
- `eventData` (SensorswaveSendEvent, required): Complete event object
  - `event` (string, required): Event name
  - `properties` (Object, optional): Event properties
  - `time` (number, required): Event timestamp in milliseconds
  - `trace_id` (string, required): Unique trace ID for the event
  - `anon_id` (string, optional): Anonymous user ID (auto-filled if not provided)
  - `login_id` (string, optional): Login user ID (auto-filled if not provided)
  - `user_properties` (Object, optional): User profile operations

**Example:**
```javascript
// Basic usage with auto-filled fields
Sensorswave.track({
  event: 'ProductPurchase',
  properties: {
    product_id: '12345',
    product_name: 'iPhone 15',
    quantity: 1,
    total_amount: 799
  },
  time: Date.now(),
  trace_id: 'purchase_12345'
});

// Advanced usage with user properties
Sensorswave.track({
  event: 'UserSignup',
  properties: {
    signup_method: 'email',
    referral_code: 'FRIEND2024'
  },
  time: Date.now(),
  trace_id: 'signup_67890',
  user_properties: {
    '$set': {
      signup_date: new Date().toISOString(),
      referral_source: 'friend'
    },
    '$set_once': {
      initial_campaign: 'spring_2024'
    }
  }
});

// With custom identity IDs
Sensorswave.track({
  event: 'CustomEvent',
  properties: { key: 'value' },
  time: Date.now(),
  trace_id: 'custom_trace_123',
  anon_id: 'custom_anon_id',
  login_id: 'user_12345'
});
```

### User Profile

#### profileSet

Set user properties. If a property already exists, it will be overwritten.

**Parameters:**
- `properties` (Object, required): User properties to set

**Example:**
```javascript
Sensorswave.profileSet({
  name: 'John Doe',
  age: 30,
  plan: 'premium',
  avatar: 'https://example.com/avatar.jpg'
});
```

#### profileSetOnce

Set user properties only if they don't already exist. Existing properties will not be overwritten.

**Parameters:**
- `properties` (Object, required): User properties to set once

**Example:**
```javascript
Sensorswave.profileSetOnce({
  first_visit_date: '2024-01-15',
  initial_referrer: 'search',
  initial_campaign: 'spring_sale'
});
```

#### profileIncrement

Increment numeric user properties by a specified amount. Only supports numeric properties.

**Parameters:**
- `properties` (Object, required): Properties to increment with numeric values

**Example:**
```javascript
// Increment single property
Sensorswave.profileIncrement({
  login_count: 1
});

// Increment multiple properties
Sensorswave.profileIncrement({
  login_count: 1,
  points_earned: 100,
  purchases_count: 1
});
```

#### profileAppend

Append new values to list-type user properties without deduplication.

**Parameters:**
- `properties` (Object, required): Properties with array values to append

**Example:**
```javascript
Sensorswave.profileAppend({
  categories_viewed: ['electronics', 'mobile_phones'],
  tags: ['new_customer', 'q1_2024']
});
```

#### profileUnion

Append new values to list-type user properties with deduplication (avoids duplicate values).

**Parameters:**
- `properties` (Object, required): Properties with array values to append with deduplication

**Example:**
```javascript
Sensorswave.profileUnion({
  interests: ['technology', 'gaming'],
  newsletter_subscriptions: ['tech_news']
});
```

#### profileUnset

Set specific user properties to null (effectively removing them).

**Parameters:**
- `propertyNames` (string[], required): Property names to unset

**Example:**
```javascript
// Unset single property
Sensorswave.profileUnset(['temporary_campaign']);

// Unset multiple properties
Sensorswave.profileUnset(['old_plan', 'expired_flag', 'temp_id']);
```

#### profileDelete

Delete all user profile data for the current user. This operation cannot be undone.

**Example:**
```javascript
Sensorswave.profileDelete();
```

### User Identification

#### identify

Set the login ID for the current user and send a binding event to associate anonymous behavior with the identified user.

**Parameters:**
- `loginId` (string | number, required): Unique identifier for the user (e.g., email, user ID, username)

**Example:**
```javascript
Sensorswave.identify('user_12345');
```

#### setLoginId

Set the login ID for the current user without sending a binding event. Use this if you want to identify the user but don't need to track the association event.

**Parameters:**
- `loginId` (string | number, required): Unique identifier for the user

**Example:**
```javascript
Sensorswave.setLoginId('user_12345');
```

#### getLoginId

Get the current login ID for the identified user.

**Returns:** string | number

**Example:**
```javascript
const loginId = Sensorswave.getLoginId();
console.log('Current login ID:', loginId);
```

#### getAnonId

Get the current anonymous ID for the user. This ID is automatically generated and persists across sessions.

**Returns:** string

**Example:**
```javascript
const anonId = Sensorswave.getAnonId();
console.log('Anonymous user ID:', anonId);
```

### Common Properties

#### registerCommonProperties

Register static or dynamic common properties that will be included with all events. This is useful for including global context like app version, environment, or user-specific data.

**Parameters:**
- `properties` (Record<string, any>, required): Properties to register
  - Static properties: string/number/boolean values
  - Dynamic properties: functions that return values (evaluated for each event)

**Example:**
```javascript
Sensorswave.registerCommonProperties({
  // Static property
  app_version: '1.0.0',
  environment: 'production',

  // Dynamic property (evaluated for each event)
  current_time: () => new Date().toISOString(),
  user_session_id: () => getSessionId()
});
```

#### clearCommonProperties

Remove specific registered common properties. If no keys are provided, all common properties will be cleared.

**Parameters:**
- `propertyNames` (string[], optional): Array of property names to remove

**Example:**
```javascript
// Clear specific properties
Sensorswave.clearCommonProperties(['app_version', 'user_session_id']);

// Clear all common properties
Sensorswave.clearCommonProperties();
```

### A/B Testing

#### checkFeatureGate

Check if a feature gate (feature flag) is enabled for the current user. Returns a promise that resolves to a boolean.

**Parameters:**
- `key` (string, required): The feature gate key to check

**Returns:** Promise<boolean>

**Example:**
```javascript
// Check if a feature is enabled
Sensorswave.checkFeatureGate('new_checkout_flow')
  .then(isEnabled => {
    if (isEnabled) {
      // Show new feature
      showNewCheckout();
    } else {
      // Show old feature
      showOldCheckout();
    }
  });

// Using async/await
async function initFeature() {
  const isEnabled = await Sensorswave.checkFeatureGate('advanced_search');
  if (isEnabled) {
    enableAdvancedSearch();
  }
}
```

#### getExperiment

Get experiment variant data for the current user. Returns a promise that resolves to the experiment configuration.

**Parameters:**
- `key` (string, required): The experiment key to retrieve

**Returns:** Promise<Object>

The returned object contains:
- Record<string, any>: Variant configuration values

**Example:**
```javascript
// Get experiment configuration
Sensorswave.getExperiment('homepage_layout')
  .then(experiment => {
    if (experiment) {
      // Apply experiment configuration
      applyLayout(experiment.layout_type);
    }
  });

// Using async/await
async function initExperiment() {
  const experiment = await Sensorswave.getExperiment('pricing_display');
  if (experiment) {
    const { price_format, discount_type } = experiment;
    updatePricingDisplay(price_format, discount_type);
  }
}
```

## Supported Event Types

The SDK automatically captures the following event types when `autoCapture` is enabled:

| Event Name | Description | Trigger Timing |
|------------|-------------|----------------|
| $MPLaunch | Mini-program launch | App.onLaunch |
| $MPShow | Mini-program show | App.onShow |
| $MPHide | Mini-program hide | App.onHide |
| $MPPageView | Page view | Page.onShow |
| $MPPageLeave | Page leave | Page.onHide |
| $MPShare | Share action | onShareAppMessage |
| $MPClick | Element click | Element tap event (when `enableClickTrack` is true) |

Custom events can be tracked using the `trackEvent()` method.

### $MPClick Event Details

When `enableClickTrack` is enabled, the SDK automatically captures click events on elements. **Important notes:**

- **Only elements with bound event handlers are tracked** — The SDK proxies Page/Component event functions, so elements must have `bindtap`/`catchtap` (or similar) handlers to be captured
- **Supported event types**: `tap`, `longtap`, `longpress`

```xml
<!-- This click WILL be tracked -->
<button bindtap="handleSubmit">Submit</button>

<!-- This click will NOT be tracked (no event binding) -->
<view>No event handler</view>
```

## Preset Properties

All events automatically include the following preset properties:

| Property Name | Type | Description |
|---------------|------|-------------|
| $lib | String | SDK identifier |
| $lib_version | String | SDK version |
| $brand | String | Device brand |
| $model | String | Device model |
| $os | String | Operating system |
| $os_version | String | Operating system version |
| $screen_width | Number | Screen width |
| $screen_height | Number | Screen height |
| $network_type | String | Network type (wifi, 4g, 5g, etc.) |
| $url_path | String | Page path |
| $url_query | String | Page query parameters (sanitized) |

## Error Handling

The SDK automatically handles the following error situations:

- **Storage full**: Degrades to in-memory storage
- **Network request failure**: Automatically retries (default 1 time)
- **A/B test timeout**: Returns default values (feature gates return false, experiments return null)
- **SDK initialization failure**: Enters degraded mode, core APIs remain available

## Debug Mode

Enable debug mode to view detailed logs:

```javascript
Sensorswave.init('your-source-token', {
  apiHost: 'https://your-api-host.com',
  debug: true
});
```

Debug logs will output:
- SDK initialization information
- Event tracking information
- Network request information
- Error information

## TypeScript Support

The SDK is written in TypeScript and includes full type definitions. If you're using TypeScript in your mini-program project, you can benefit from type checking and IntelliSense.

```typescript
import Sensorswave from '@sensorswave/wechat-mini';

// Type-safe API calls
Sensorswave.init('your-source-token', {
  apiHost: 'https://your-api-host.com',
  autoCapture: true,
  batchSend: true,
  enableAB: false,
  enableClickTrack: false,
  debug: false
});

Sensorswave.trackEvent('ButtonClick', {
  button_name: 'submit',
  page: 'home'
});

const isEnabled: boolean = await Sensorswave.checkFeatureGate('new_feature');
```

## License

Apache-2.0