Firebase如何为每个Token推送含不同数据的消息?
Hey there, I get it—you're trying to send FCM messages to 1000 tokens, but need each user to get a unique click_action link to track their clicks. The problem with using registration_ids is that it sends a single, identical payload to all devices, so you can't customize the link per token. Let's go over two solid solutions for this:
Solution 1: Send Individual Messages (Simple & Straightforward)
For 1000 tokens, looping through each one and sending a separate message is totally feasible—FCM's rate limits handle this easily. You just need to pair each token with its unique tracking parameter (like a user ID or unique hash) and build a custom payload for each.
Here's a PHP example matching your existing code style:
// Assume $tokens is an array of objects/arrays with token + user identifier, e.g.: // $tokens = [['token' => 'abc123', 'user_id' => 'user_456'], ...] foreach ($tokens as $userToken) { // Build unique tracked link with user-specific parameter $trackedLink = "https://site.ru?track_id=" . $userToken['user_id']; $payload = [ 'to' => $userToken['token'], 'data' => [ 'title' => 'Title', 'body' => 'Message', 'icon' => 'icon.png', 'image' => 'image.png', 'click_action' => $trackedLink ] ]; // Send the request to FCM $ch = curl_init("https://fcm.googleapis.com/fcm/send"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: key=YOUR_FCM_SERVER_KEY', 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); $response = curl_exec($ch); curl_close($ch); // Optional: Log success/failure for each send }
Pros: Dead simple to implement, full control over each user's link.
Cons: Sends 1000 separate requests, but this is negligible for 1000 tokens.
Solution 2: Use FCM Multicast Messages (Recommended for Admin SDK Users)
If you're using the Firebase Admin SDK (like the PHP kreait/firebase-php package), the MulticastMessage feature lets you send personalized messages in optimized batches. The SDK handles grouping requests efficiently, so it's faster than manual loops.
Example code:
use Kreait\Firebase\Factory; use Kreait\Firebase\Messaging\MulticastMessage; use Kreait\Firebase\Messaging\CloudMessage; // Initialize Firebase Admin SDK $factory = (new Factory)->withServiceAccount(__DIR__.'/your-firebase-credentials.json'); $messaging = $factory->createMessaging(); // Build individual messages for each token $individualMessages = []; foreach ($tokens as $userToken) { $trackedLink = "https://site.ru?track_id=" . $userToken['user_id']; $individualMessages[] = CloudMessage::withTarget('token', $userToken['token']) ->withData([ 'title' => 'Title', 'body' => 'Message', 'icon' => 'icon.png', 'image' => 'image.png', 'click_action' => $trackedLink ]); } // Send as multicast $response = $messaging->sendMulticast(MulticastMessage::fromMessages($individualMessages)); // Handle results echo "Successfully sent to " . $response->successes()->count() . " devices\n"; echo "Failed to send to " . $response->failures()->count() . " devices\n";
Pros: More efficient than manual loops, built-in error handling, and SDK optimizations.
Cons: Requires setting up the Firebase Admin SDK (worth it if you're working with Firebase regularly).
Key Notes
- Make sure you store each token alongside a unique user identifier (like user ID) so you can generate the personalized link.
- If you were using the
notificationfield before, avoid settingclick_actionthere—keep all personalized data in thedatafield to ensure the unique link takes priority. - FCM's
registration_idslimit is 1000 tokens per request anyway, so splitting into individual/multicast messages is necessary for larger lists too.
内容的提问来源于stack exchange,提问作者Rufex

