0
# Topic Management
1
2
Topic subscription management for targeted messaging campaigns. Topics allow apps to subscribe to and receive messages sent to specific categories or interests.
3
4
## Capabilities
5
6
### Subscribe to Topic
7
8
Subscribe the device to a named topic to receive targeted messages sent to that topic.
9
10
```typescript { .api }
11
/**
12
* Subscribe device to a topic for targeted messaging
13
* @param topic - Topic name (must not contain forward slashes)
14
* @returns Promise that resolves when subscription is complete
15
*/
16
function subscribeToTopic(topic: string): Promise<void>;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import messaging from '@react-native-firebase/messaging';
23
24
// Subscribe to news updates
25
await messaging().subscribeToTopic('news');
26
console.log('Subscribed to news topic');
27
28
// Subscribe to user-specific topics
29
const userId = getCurrentUserId();
30
await messaging().subscribeToTopic(`user_${userId}`);
31
32
// Subscribe to multiple topics
33
const topics = ['sports', 'weather', 'breaking-news'];
34
await Promise.all(
35
topics.map(topic => messaging().subscribeToTopic(topic))
36
);
37
38
// Modular API
39
import { getMessaging, subscribeToTopic } from '@react-native-firebase/messaging';
40
const messagingInstance = getMessaging();
41
await subscribeToTopic(messagingInstance, 'news');
42
```
43
44
### Unsubscribe from Topic
45
46
Unsubscribe the device from a topic to stop receiving messages sent to that topic.
47
48
```typescript { .api }
49
/**
50
* Unsubscribe device from a topic
51
* @param topic - Topic name to unsubscribe from
52
* @returns Promise that resolves when unsubscription is complete
53
*/
54
function unsubscribeFromTopic(topic: string): Promise<void>;
55
```
56
57
**Usage Examples:**
58
59
```typescript
60
import messaging from '@react-native-firebase/messaging';
61
62
// Unsubscribe from news updates
63
await messaging().unsubscribeFromTopic('news');
64
console.log('Unsubscribed from news topic');
65
66
// Unsubscribe when user logs out
67
const userId = getCurrentUserId();
68
await messaging().unsubscribeFromTopic(`user_${userId}`);
69
70
// Unsubscribe from multiple topics
71
const topics = ['sports', 'weather'];
72
await Promise.all(
73
topics.map(topic => messaging().unsubscribeFromTopic(topic))
74
);
75
76
// Modular API
77
import { getMessaging, unsubscribeFromTopic } from '@react-native-firebase/messaging';
78
const messagingInstance = getMessaging();
79
await unsubscribeFromTopic(messagingInstance, 'news');
80
```
81
82
## Topic Rules and Limitations
83
84
### Topic Name Requirements
85
86
- **No Forward Slashes**: Topic names must not contain `/` characters
87
- **Case Sensitive**: Topic names are case-sensitive
88
- **Character Limit**: Maximum length varies by platform but typically 900 characters
89
- **Valid Characters**: Alphanumeric characters, hyphens, and underscores recommended
90
91
### Subscription Limits
92
93
- **Per App**: Up to 2000 topic subscriptions per app instance
94
- **Global**: No limit on total subscribers to a topic
95
- **Propagation**: Subscriptions may take up to 24 hours to propagate
96
97
### Error Conditions
98
99
Topics with invalid names will throw errors:
100
101
```typescript
102
// These will throw errors
103
try {
104
await messaging().subscribeToTopic('news/sports'); // Contains forward slash
105
} catch (error) {
106
console.error('Invalid topic name:', error.message);
107
}
108
109
try {
110
await messaging().subscribeToTopic(''); // Empty topic name
111
} catch (error) {
112
console.error('Empty topic name:', error.message);
113
}
114
```
115
116
## Topic Management Patterns
117
118
### User Preference Topics
119
120
```typescript
121
import messaging from '@react-native-firebase/messaging';
122
123
class TopicManager {
124
static async updateUserTopics(preferences: UserPreferences) {
125
const messaging = messaging();
126
127
// Subscribe to enabled topics
128
for (const topic of preferences.enabledTopics) {
129
await messaging.subscribeToTopic(topic);
130
}
131
132
// Unsubscribe from disabled topics
133
for (const topic of preferences.disabledTopics) {
134
await messaging.unsubscribeFromTopic(topic);
135
}
136
}
137
138
static async subscribeToUserSpecificTopics(userId: string) {
139
const messaging = messaging();
140
141
// Personal notifications
142
await messaging.subscribeToTopic(`user_${userId}`);
143
144
// Account-related updates
145
await messaging.subscribeToTopic(`account_${userId}`);
146
}
147
148
static async unsubscribeFromUserTopics(userId: string) {
149
const messaging = messaging();
150
151
await messaging.unsubscribeFromTopic(`user_${userId}`);
152
await messaging.unsubscribeFromTopic(`account_${userId}`);
153
}
154
}
155
156
// Usage
157
await TopicManager.subscribeToUserSpecificTopics('user123');
158
await TopicManager.updateUserTopics({
159
enabledTopics: ['news', 'sports'],
160
disabledTopics: ['weather', 'politics']
161
});
162
```
163
164
### Geographic Topics
165
166
```typescript
167
import messaging from '@react-native-firebase/messaging';
168
169
class LocationTopicManager {
170
static async updateLocationTopics(
171
oldLocation: string | null,
172
newLocation: string
173
) {
174
const messaging = messaging();
175
176
// Unsubscribe from old location
177
if (oldLocation) {
178
await messaging.unsubscribeFromTopic(`location_${oldLocation}`);
179
await messaging.unsubscribeFromTopic(`weather_${oldLocation}`);
180
}
181
182
// Subscribe to new location
183
await messaging.subscribeToTopic(`location_${newLocation}`);
184
await messaging.subscribeToTopic(`weather_${newLocation}`);
185
}
186
}
187
188
// Usage
189
await LocationTopicManager.updateLocationTopics('new-york', 'san-francisco');
190
```
191
192
### App Version Topics
193
194
```typescript
195
import messaging from '@react-native-firebase/messaging';
196
import { getVersion } from 'react-native-device-info';
197
198
class VersionTopicManager {
199
static async subscribeToVersionTopics() {
200
const messaging = messaging();
201
const version = await getVersion();
202
203
// Subscribe to version-specific updates
204
await messaging.subscribeToTopic(`version_${version.replace(/\./g, '_')}`);
205
206
// Subscribe to major version updates
207
const majorVersion = version.split('.')[0];
208
await messaging.subscribeToTopic(`major_version_${majorVersion}`);
209
}
210
}
211
212
// Usage
213
await VersionTopicManager.subscribeToVersionTopics();
214
```
215
216
## Server-Side Topic Messaging
217
218
Topics are managed server-side through Firebase Admin SDK or HTTP API:
219
220
### Admin SDK Example (Node.js)
221
222
```typescript
223
// Server-side code (not React Native)
224
import admin from 'firebase-admin';
225
226
// Send to topic
227
const message = {
228
notification: {
229
title: 'Breaking News',
230
body: 'Important update for all news subscribers',
231
},
232
topic: 'news'
233
};
234
235
await admin.messaging().send(message);
236
237
// Send to multiple topics
238
const multiTopicMessage = {
239
notification: {
240
title: 'Weather Alert',
241
body: 'Severe weather warning',
242
},
243
condition: "'weather' in topics && 'severe-alerts' in topics"
244
};
245
246
await admin.messaging().send(multiTopicMessage);
247
```
248
249
## Best Practices
250
251
1. **Descriptive Names**: Use clear, descriptive topic names
252
2. **Hierarchical Structure**: Consider using prefixes for organization (`news_sports`, `news_politics`)
253
3. **User Control**: Always provide users control over topic subscriptions
254
4. **Cleanup**: Unsubscribe from user-specific topics on logout
255
5. **Error Handling**: Handle network errors during subscription/unsubscription
256
6. **Batch Operations**: Use `Promise.all()` for multiple topic operations
257
7. **Topic Limits**: Monitor subscription count to stay within limits
258
259
## Topic Subscription Management
260
261
```typescript
262
import messaging from '@react-native-firebase/messaging';
263
264
class TopicSubscriptionManager {
265
private static subscriptions = new Set<string>();
266
267
static async subscribe(topic: string): Promise<boolean> {
268
try {
269
await messaging().subscribeToTopic(topic);
270
this.subscriptions.add(topic);
271
console.log(`Subscribed to topic: ${topic}`);
272
return true;
273
} catch (error) {
274
console.error(`Failed to subscribe to ${topic}:`, error);
275
return false;
276
}
277
}
278
279
static async unsubscribe(topic: string): Promise<boolean> {
280
try {
281
await messaging().unsubscribeFromTopic(topic);
282
this.subscriptions.delete(topic);
283
console.log(`Unsubscribed from topic: ${topic}`);
284
return true;
285
} catch (error) {
286
console.error(`Failed to unsubscribe from ${topic}:`, error);
287
return false;
288
}
289
}
290
291
static getSubscriptions(): string[] {
292
return Array.from(this.subscriptions);
293
}
294
295
static async unsubscribeAll(): Promise<void> {
296
const unsubscribePromises = Array.from(this.subscriptions).map(
297
topic => this.unsubscribe(topic)
298
);
299
await Promise.all(unsubscribePromises);
300
}
301
}
302
```