mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
🎨 Polish the documentation
This commit is contained in:
parent
0ba6de569b
commit
8cf8ccf061
1 changed files with 117 additions and 25 deletions
|
@ -7,6 +7,33 @@ It monitors WordPress data stores rather than adding code to frontend components
|
||||||
|
|
||||||
## Architecture Components
|
## Architecture Components
|
||||||
|
|
||||||
|
### File/Folder Organization
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── services/
|
||||||
|
│ └── tracking/
|
||||||
|
│ ├── registry.js # Central funnel registration
|
||||||
|
│ ├── subscription-manager.js # Store subscription management
|
||||||
|
│ ├── utils.js # Field config helpers & utilities
|
||||||
|
│ ├── adapters/ # Tracking destination adapters
|
||||||
|
│ │ ├── woocommerce-tracks.js # WooCommerce Tracks integration
|
||||||
|
│ │ └── console-logger.js # Console output
|
||||||
|
│ └── funnels/ # Funnel-specific configurations
|
||||||
|
│ └── onboarding.js # Onboarding funnel config & translations
|
||||||
|
├── data/ # Enhanced Redux stores
|
||||||
|
│ ├── onboarding/
|
||||||
|
│ │ ├── actions.js # Enhanced with source parameter
|
||||||
|
│ │ ├── reducer.js # Enhanced with field source tracking
|
||||||
|
│ │ └── hooks.js # Enhanced to pass source values
|
||||||
|
│ └── common/
|
||||||
|
│ ├── actions.js # Enhanced with source parameter
|
||||||
|
│ ├── reducer.js # Enhanced with field source tracking
|
||||||
|
│ └── hooks.js # Enhanced to pass source values
|
||||||
|
└── components/ # Enhanced to pass tracking sources
|
||||||
|
└── **/*.js # Form components updated with source attribution
|
||||||
|
```
|
||||||
|
|
||||||
### 1. Registry System (`src/services/tracking/registry.js`)
|
### 1. Registry System (`src/services/tracking/registry.js`)
|
||||||
|
|
||||||
The registry manages funnel registration and coordinates multiple tracking concerns without conflicts.
|
The registry manages funnel registration and coordinates multiple tracking concerns without conflicts.
|
||||||
|
@ -61,7 +88,7 @@ const subscription = wp.data.subscribe(() => {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Source-Based Field Filtering
|
### 3. Source-Based Field Filtering (`src/services/tracking/utils.js`, `subscription-manager.js`)
|
||||||
|
|
||||||
**Why Source Tracking?** Redux store subscriptions and internal system updates were creating noise in analytics by triggering tracking events for non-user actions.
|
**Why Source Tracking?** Redux store subscriptions and internal system updates were creating noise in analytics by triggering tracking events for non-user actions.
|
||||||
|
|
||||||
|
@ -79,14 +106,12 @@ fieldRules: {
|
||||||
// Usage in components
|
// Usage in components
|
||||||
const { setIsCasualSeller } = useOnboardingHooks();
|
const { setIsCasualSeller } = useOnboardingHooks();
|
||||||
setIsCasualSeller(true, 'user'); // Will be tracked
|
setIsCasualSeller(true, 'user'); // Will be tracked
|
||||||
setIsCasualSeller(false, 'subscription'); // Will be filtered out
|
setIsCasualSeller(false); // Will be filtered out
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Source Types
|
#### Source Types
|
||||||
- `'user'` - Direct user interactions (form inputs, button clicks)
|
- `'user'` - Direct user interactions (form inputs, button clicks)
|
||||||
- `'system'` - System-initiated changes (auto-progression, defaults)
|
- `'system'` - System-initiated changes (data loaded from settings, defaults)
|
||||||
- `'subscription'` - Changes from store subscriptions (filtered out)
|
|
||||||
- `'api'` - Changes from API responses
|
|
||||||
|
|
||||||
### 4. Adapter Pattern (`src/services/tracking/adapters/`)
|
### 4. Adapter Pattern (`src/services/tracking/adapters/`)
|
||||||
|
|
||||||
|
@ -94,9 +119,8 @@ Supports multiple tracking backends through a consistent interface.
|
||||||
|
|
||||||
#### Available Adapters
|
#### Available Adapters
|
||||||
|
|
||||||
##### WooCommerce Tracks Adapter
|
##### WooCommerce Tracks Adapter (`src/services/tracking/adapters/woocommerce-tracks.js`)
|
||||||
```javascript
|
```javascript
|
||||||
// src/services/tracking/adapters/woocommerce-tracks.js
|
|
||||||
class WooCommerceTracksAdapter {
|
class WooCommerceTracksAdapter {
|
||||||
sendEvent(eventName, properties) {
|
sendEvent(eventName, properties) {
|
||||||
if (window.wcTracks?.recordEvent) {
|
if (window.wcTracks?.recordEvent) {
|
||||||
|
@ -106,9 +130,8 @@ class WooCommerceTracksAdapter {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Console Logger Adapter
|
##### Console Logger Adapter (`src/services/tracking/adapters/console-logger.js`)
|
||||||
```javascript
|
```javascript
|
||||||
// src/services/tracking/adapters/console-logger.js
|
|
||||||
class ConsoleLoggerAdapter {
|
class ConsoleLoggerAdapter {
|
||||||
sendEvent(eventName, properties) {
|
sendEvent(eventName, properties) {
|
||||||
console.log(`🎯 ${eventName}`, properties);
|
console.log(`🎯 ${eventName}`, properties);
|
||||||
|
@ -118,6 +141,7 @@ class ConsoleLoggerAdapter {
|
||||||
|
|
||||||
#### Creating Custom Adapters
|
#### Creating Custom Adapters
|
||||||
```javascript
|
```javascript
|
||||||
|
// src/services/tracking/adapters/your-custom-adapter.js
|
||||||
class CustomAnalyticsAdapter {
|
class CustomAnalyticsAdapter {
|
||||||
sendEvent(eventName, properties) {
|
sendEvent(eventName, properties) {
|
||||||
// Your custom implementation
|
// Your custom implementation
|
||||||
|
@ -125,17 +149,19 @@ class CustomAnalyticsAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the adapter
|
// Register in funnel configuration
|
||||||
trackingService.addAdapter(new CustomAnalyticsAdapter());
|
trackingService.addAdapter(new CustomAnalyticsAdapter());
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Translation Functions (`src/services/tracking/funnels/`)
|
### 5. Funnel Configurations & Translation Functions (`src/services/tracking/funnels/`)
|
||||||
|
|
||||||
Transform generic field changes into meaningful business events with rich context.
|
Each funnel gets its own file containing both configuration and translation functions.
|
||||||
|
|
||||||
#### Example Translation
|
#### Example: Onboarding Funnel (`src/services/tracking/funnels/onboarding.js`)
|
||||||
```javascript
|
```javascript
|
||||||
// src/services/tracking/funnels/onboarding.js
|
import { createFieldTrackingConfig, createBooleanFieldConfig } from '../utils';
|
||||||
|
|
||||||
|
// Translation functions for this funnel
|
||||||
export const translations = {
|
export const translations = {
|
||||||
isCasualSeller: (oldValue, newValue, metadata, trackingService) => {
|
isCasualSeller: (oldValue, newValue, metadata, trackingService) => {
|
||||||
const accountType = newValue === true ? 'personal' : 'business';
|
const accountType = newValue === true ? 'personal' : 'business';
|
||||||
|
@ -162,6 +188,31 @@ export const translations = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Funnel configuration
|
||||||
|
export const onboardingFunnelConfig = {
|
||||||
|
funnelId: 'onboarding',
|
||||||
|
stores: ['wc/paypal/onboarding', 'wc/paypal/common'],
|
||||||
|
|
||||||
|
trackingCondition: {
|
||||||
|
store: 'wc/paypal/common',
|
||||||
|
selector: 'merchant',
|
||||||
|
field: 'isConnected',
|
||||||
|
expectedValue: false
|
||||||
|
},
|
||||||
|
|
||||||
|
fieldConfigs: {
|
||||||
|
'wc/paypal/onboarding': [
|
||||||
|
createFieldTrackingConfig('step', 'persistent', {
|
||||||
|
rules: { allowedSources: ['user', 'system'] }
|
||||||
|
}),
|
||||||
|
createBooleanFieldConfig('isCasualSeller', 'persistent', ['user'])
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
translations,
|
||||||
|
debug: process.env.NODE_ENV === 'development'
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -234,16 +285,18 @@ const onboardingFunnelConfig = {
|
||||||
|
|
||||||
## Integration with Redux Stores
|
## Integration with Redux Stores
|
||||||
|
|
||||||
### Action Enhancement
|
### Action Enhancement (`src/data/{store}/actions.js`)
|
||||||
|
|
||||||
PayPal store actions for tracked fields have been enhanced to support source tracking. **Note:** Source tracking support must be manually added to specific actions when you want to track new fields or extend tracking to additional data stores.
|
Store actions for tracked fields have been enhanced to support source tracking. **Note:** Source tracking support must be manually added to specific actions when you want to track new fields or extend tracking to additional data stores.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// src/data/onboarding/actions.js
|
||||||
|
|
||||||
// Before
|
// Before
|
||||||
export const setIsCasualSeller = (isCasualSeller) =>
|
export const setIsCasualSeller = (isCasualSeller) =>
|
||||||
setPersistent('isCasualSeller', isCasualSeller);
|
setPersistent('isCasualSeller', isCasualSeller);
|
||||||
|
|
||||||
// After
|
// After
|
||||||
export const setIsCasualSeller = (isCasualSeller, source = 'user') =>
|
export const setIsCasualSeller = (isCasualSeller, source = 'user') =>
|
||||||
setPersistent('isCasualSeller', isCasualSeller, source);
|
setPersistent('isCasualSeller', isCasualSeller, source);
|
||||||
```
|
```
|
||||||
|
@ -252,14 +305,14 @@ export const setIsCasualSeller = (isCasualSeller, source = 'user') =>
|
||||||
|
|
||||||
To add source tracking to additional fields, you need to:
|
To add source tracking to additional fields, you need to:
|
||||||
|
|
||||||
1. **Update the action creator** to accept and pass the source parameter:
|
1. **Update the action creator** (`src/data/{store}/actions.js`) to accept and pass the source parameter:
|
||||||
```javascript
|
```javascript
|
||||||
// Add source parameter to action creator
|
// Add source parameter to action creator
|
||||||
export const setNewField = (value, source = 'user') =>
|
export const setNewField = (value, source = 'user') =>
|
||||||
setPersistent('newField', value, source);
|
setPersistent('newField', value, source);
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Update the hook** to pass source values:
|
2. **Update the hook** (`src/data/{store}/hooks.js`) to pass source values:
|
||||||
```javascript
|
```javascript
|
||||||
// In hooks file
|
// In hooks file
|
||||||
const setNewField = async (value, source = 'user') => {
|
const setNewField = async (value, source = 'user') => {
|
||||||
|
@ -268,7 +321,7 @@ const setNewField = async (value, source = 'user') => {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Add field configuration** to your funnel:
|
3. **Add field configuration** to your funnel (`src/services/tracking/funnels/{funnel-name}.js`):
|
||||||
```javascript
|
```javascript
|
||||||
fieldConfigs: {
|
fieldConfigs: {
|
||||||
'your-store-name': [
|
'your-store-name': [
|
||||||
|
@ -283,7 +336,7 @@ fieldConfigs: {
|
||||||
|
|
||||||
To extend tracking to a new data store:
|
To extend tracking to a new data store:
|
||||||
|
|
||||||
1. **Enhance the base actions** (`setPersistent`/`setTransient`) to handle source:
|
1. **Enhance the base actions** (`src/data/{new-store}/actions.js`) - add `setPersistent`/`setTransient` to handle source:
|
||||||
```javascript
|
```javascript
|
||||||
// In your new store's actions.js
|
// In your new store's actions.js
|
||||||
export const setPersistent = (prop, value, source) => ({
|
export const setPersistent = (prop, value, source) => ({
|
||||||
|
@ -294,7 +347,7 @@ export const setPersistent = (prop, value, source) => ({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Update the reducer** to track field sources:
|
2. **Update the reducer** (`src/data/{new-store}/reducer.js`) to track field sources:
|
||||||
```javascript
|
```javascript
|
||||||
// In your reducer
|
// In your reducer
|
||||||
case ACTION_TYPES.SET_PERSISTENT:
|
case ACTION_TYPES.SET_PERSISTENT:
|
||||||
|
@ -313,7 +366,19 @@ case ACTION_TYPES.SET_PERSISTENT:
|
||||||
return newState;
|
return newState;
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Register the store** in your funnel configuration:
|
3. **Create enhanced hooks** (`src/data/{new-store}/hooks.js`) that pass source values:
|
||||||
|
```javascript
|
||||||
|
export const useNewStoreHooks = () => {
|
||||||
|
return {
|
||||||
|
setNewField: async (value, source = 'user') => {
|
||||||
|
setNewFieldAction(value, source);
|
||||||
|
await dispatchActions.persist();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Register the store** in your funnel configuration (`src/services/tracking/funnels/{funnel-name}.js`):
|
||||||
```javascript
|
```javascript
|
||||||
registerTrackingFunnel('your-funnel', {
|
registerTrackingFunnel('your-funnel', {
|
||||||
stores: ['your-new-store-name'],
|
stores: ['your-new-store-name'],
|
||||||
|
@ -321,7 +386,7 @@ registerTrackingFunnel('your-funnel', {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Reducer Enhancement
|
### Reducer Enhancement (`src/data/{onboarding,common}/reducer.js`)
|
||||||
|
|
||||||
Reducers automatically handle field source tracking (only for onboarding and common data stores for now):
|
Reducers automatically handle field source tracking (only for onboarding and common data stores for now):
|
||||||
|
|
||||||
|
@ -342,11 +407,12 @@ case ACTION_TYPES.SET_PERSISTENT:
|
||||||
return newState;
|
return newState;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Hook Integration
|
### Hook Integration (`src/data/{onboarding,common}/hooks.js`)
|
||||||
|
|
||||||
Custom hooks pass appropriate source values (only for onboarding and common data stores for now):
|
Custom hooks pass appropriate source values (only for onboarding and common data stores for now):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
// src/data/onboarding/hooks.js
|
||||||
export const useOnboardingHooks = () => {
|
export const useOnboardingHooks = () => {
|
||||||
const { setIsCasualSeller: setIsCasualSellerAction } = useActions();
|
const { setIsCasualSeller: setIsCasualSellerAction } = useActions();
|
||||||
|
|
||||||
|
@ -359,6 +425,32 @@ export const useOnboardingHooks = () => {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Component Integration (`src/components/**/*.js`)
|
||||||
|
|
||||||
|
Update form components and user interaction handlers to pass appropriate source values:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// src/components/onboarding/AccountTypeSelector.js
|
||||||
|
import { useOnboardingHooks } from '../../data/onboarding/hooks';
|
||||||
|
|
||||||
|
const AccountTypeSelector = () => {
|
||||||
|
const { setIsCasualSeller } = useOnboardingHooks();
|
||||||
|
|
||||||
|
const handleAccountTypeChange = (accountType) => {
|
||||||
|
const isCasual = accountType === 'personal';
|
||||||
|
setIsCasualSeller(isCasual, 'user'); // Specify 'user' source for tracking
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select onChange={(e) => handleAccountTypeChange(e.target.value)}>
|
||||||
|
<option value="business">Business</option>
|
||||||
|
<option value="personal">Personal</option>
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Event Schema
|
## Event Schema
|
||||||
|
|
||||||
### Event Naming Convention
|
### Event Naming Convention
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue