registerDevice()
Registers a mobile device for a user to enable push notifications.
Signature
async registerDevice(
identifier: string,
deviceParams: DeviceRegistrationParameters
): Promise<void>
Parameters
identifier
- Type:
string - Required: Yes
- Description: User identifier (must match the one used in
identify())
deviceParams
- Type:
DeviceRegistrationParameters - Required: Yes
- Description: Device information and credentials
DeviceRegistrationParameters Interface
interface DeviceRegistrationParameters {
// Required
deviceId: string;
platform: 'android' | 'ios' | 'web';
fcmToken: string;
// Optional
name?: string;
osVersion?: string;
model?: string;
apnToken?: string;
appVersion?: string;
last_active_at?: string;
attributes?: Record<string, any>;
}
Required Fields
deviceId- Unique identifier for the deviceplatform- Device platform ('android','ios', or'web')fcmToken- Firebase Cloud Messaging token
Device ID Requirements
The deviceId must be:
- Unique to each physical device
- Consistent for that device across all registrations
Each device should always use the same deviceId. Never generate a new ID for the same device.
Why this matters:
- Ensures push notifications are delivered to the correct devices
- Prevents duplicate device registrations
- Allows proper tracking of device-specific analytics
- Enables device management (e.g., removing old devices)
Common mistakes to avoid:
// ❌ Bad - Generates new ID every time
await client.registerDevice(userId, {
deviceId: uuidv4(), // DON'T DO THIS
platform: 'ios',
fcmToken: token
});
// ❌ Bad - Using non-persistent identifiers
await client.registerDevice(userId, {
deviceId: Date.now().toString(), // Changes every time
platform: 'ios',
fcmToken: token
});
// ✅ Good - Consistent, persistent device ID
const deviceId = await getOrCreateDeviceId(); // Same ID always
await client.registerDevice(userId, {
deviceId,
platform: 'ios',
fcmToken: token
});
Returns
Promise<void> - Resolves when the device is registered successfully.
Throws
- Error: If identifier or required device fields are invalid
- Network errors: If the request fails
Identifier Consistency
The identifier parameter must match the one used in identify(). See Consistent Identifiers for best practices.
Usage Examples
Register iOS Device
await client.registerDevice('user123', {
deviceId: 'device_abc123',
platform: 'ios',
fcmToken: 'fcm_token_here',
apnToken: 'apns_token_here',
osVersion: '17.0',
model: 'iPhone 14 Pro',
appVersion: '1.2.3',
name: 'John\'s iPhone'
});
Register Android Device
await client.registerDevice('user123', {
deviceId: 'device_xyz789',
platform: 'android',
fcmToken: 'fcm_token_here',
osVersion: '14.0',
model: 'Samsung Galaxy S23',
appVersion: '1.2.3',
name: 'John\'s Samsung'
});
Register Web Device
await client.registerDevice('user123', {
deviceId: 'web_session_abc',
platform: 'web',
fcmToken: 'fcm_web_token_here',
attributes: {
browser: 'Chrome',
browser_version: '119.0',
os: 'macOS'
}
});
Minimal Registration
// Only required fields
await client.registerDevice('user123', {
deviceId: 'device_minimal',
platform: 'ios',
fcmToken: 'fcm_token_here'
});
Device Attributes
You can include custom attributes for segmentation and analytics:
await client.registerDevice('user123', {
deviceId: 'device_123',
platform: 'ios',
fcmToken: 'fcm_token_here',
appVersion: '2.0.0',
attributes: {
app_language: 'en',
notification_sound: 'default',
push_enabled: true,
install_date: '2025-01-15',
device_timezone: 'America/New_York',
screen_size: 'large'
}
});
Token Refresh
FCM tokens can change. Update the device registration when this happens:
// React Native example
import messaging from '@react-native-firebase/messaging';
messaging().onTokenRefresh(async (newToken) => {
try {
await cdpClient.registerDevice(userId, {
deviceId: deviceId, // Same device ID
platform: Platform.OS === 'ios' ? 'ios' : 'android',
fcmToken: newToken, // Updated token
appVersion: getAppVersion(),
last_active_at: new Date().toISOString()
});
console.log('FCM token refreshed');
} catch (error) {
console.error('Failed to update FCM token:', error);
}
});
Updating Device Information
Re-register a device to update its information:
// Update app version after app update
await client.registerDevice('user123', {
deviceId: 'device_abc123', // Same device ID
platform: 'ios',
fcmToken: currentFcmToken,
appVersion: '2.0.0', // New version
last_active_at: new Date().toISOString()
});
Multiple Devices Per User
Users can have multiple registered devices:
// Register iPhone
await client.registerDevice('user123', {
deviceId: 'iphone_abc',
platform: 'ios',
fcmToken: 'token_iphone',
name: 'John\'s iPhone'
});
// Register iPad
await client.registerDevice('user123', {
deviceId: 'ipad_xyz',
platform: 'ios',
fcmToken: 'token_ipad',
name: 'John\'s iPad'
});
// Register Android phone
await client.registerDevice('user123', {
deviceId: 'android_def',
platform: 'android',
fcmToken: 'token_android',
name: 'John\'s Android'
});
// Send push - will go to all registered devices
await client.sendPush({
identifiers: { id: 'user123' },
transactional_message_id: 'WELCOME',
title: 'Welcome!',
body: 'Thanks for joining'
});
Error Handling
try {
await client.registerDevice('user123', {
deviceId: 'device_abc',
platform: 'ios',
fcmToken: 'fcm_token_here'
});
console.log('Device registered successfully');
} catch (error) {
if (error.message.includes('Identifier cannot be empty')) {
console.error('Invalid user identifier');
} else if (error.response?.status === 401) {
console.error('Invalid API key');
} else {
console.error('Failed to register device:', error.message);
}
}
Dual-Write Behavior
When dual-write is enabled, device registration is sent to both Conviso and Customer.io:
const client = new CDPClient({
cdpApiKey: 'your-cdp-key',
sendToCustomerIo: true,
customerIo: {
siteId: 'your-cio-site-id',
apiKey: 'your-cio-api-key'
}
});
// Registers device in both platforms
await client.registerDevice('user123', {
deviceId: 'device_abc',
platform: 'ios',
fcmToken: 'fcm_token_here'
});
If the Customer.io request fails, it's logged but doesn't throw (Conviso registration still succeeds).
Best Practices
1. Register Early
// ✅ Good - Register as soon as user is authenticated
async function handleLogin(userId: string) {
await authenticateUser(userId);
// Register device immediately
await registerDevice(userId);
}
2. Update on App Launch
// ✅ Good - Update device info on each launch
async function onAppLaunch() {
const userId = await getCurrentUserId();
if (userId) {
await client.registerDevice(userId, {
deviceId: getDeviceId(),
platform: getPlatform(),
fcmToken: await getFCMToken(),
appVersion: getAppVersion(),
last_active_at: new Date().toISOString()
});
}
}
3. Handle Token Refresh
// ✅ Good - Listen for token changes
messaging().onTokenRefresh(async (newToken) => {
await updateDeviceToken(newToken);
});
Debug Mode
const client = new CDPClient({
cdpApiKey: process.env.CDP_API_KEY,
debug: true // See detailed logs
});
await client.registerDevice('user123', {
deviceId: 'device_abc',
platform: 'ios',
fcmToken: 'token'
});
Related
- sendPush() - Send push notifications
- identify() - Identify users
- Push Examples
- Error Handling Guide