Sending Virtual Gifts - iOS
Virtual gifting is a powerful monetization and engagement feature that allows viewers to support hosts or speakers during a livestream by sending them digital tokens or "gifts." These gifts can be visually animated and even linked to leaderboards or reward systems.
This guide explains how to implement a secure and real-time virtual gifting experience using your backend server in combination with VideoSDK PubSub.
How It Works
-
User Action: A viewer taps on a gift button to send a virtual gift to the host.
-
Server Verification:
- A request is made to your business backend to process the gift.
- The server authenticates the user, checks their wallet balance, deducts the gift value, and returns a success response.
-
Event Broadcast: Upon success, the client publishes a PubSub message to inform everyone in the meeting (host + other viewers) that a gift has been sent. Clients can then visually show an animation or notification.
Backend Responsibility
Your backend plays a central role in verifying, validating, and processing gift transactions. It should:
- Authenticate the request (token/session)
- Verify if the user has sufficient balance
- Deduct the gift cost
- Store the transaction in a database (optional but recommended)
- Respond with success or failure
Frontend Implementation
- Sending a Gift (Client to Backend + PubSub)
import UIKit
import VideoSDKRTC
class GiftSenderViewController: UIViewController {
var meeting: Meeting!
func sendGift(giftType: String, senderId: String, hostId: String) {
let url = URL(string: "https://your-api.com/send-gift")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body: [String: Any] = [
"senderId": senderId,
"hostId": hostId,
"giftType": giftType
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let success = json["success"] as? Bool,
success
else {
DispatchQueue.main.async {
self.showAlert(message: "Gift could not be sent.")
}
return
}
// Publish the gift event
let message: [String: Any] = [
"giftType": giftType,
"from": senderId,
"to": hostId
]
self.meeting.pubSub.publish(topic: "GIFT", message: message, options: ["persist": true])
}
task.resume()
}
func showAlert(message: String) {
let alert = UIAlertController(title: "Gift", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
- Displaying the Gift (All Clients)
import UIKit
import VideoSDKRTC
class GiftReceiverViewController: UIViewController, PubSubMessageListener {
var meeting: Meeting! // Assume this is your current meeting instance
var gifts: [[String: Any]] = []
override func viewDidLoad() {
super.viewDidLoad()
meeting.pubSub.subscribe(topic: "GIFT", forListener: self)
}
func onMessageReceived(message: PubSubMessage) {
guard let giftData = message.message as? [String: Any] else { return }
gifts.append(giftData)
DispatchQueue.main.async {
self.displayGiftToast(giftData: giftData)
}
}
func displayGiftToast(giftData: [String: Any]) {
guard
let from = giftData["from"] as? String,
let to = giftData["to"] as? String,
let giftType = giftData["giftType"] as? String
else { return }
let toast = UILabel()
toast.text = "🎁 \(from) sent a \(giftType) to \(to)"
toast.backgroundColor = UIColor.black.withAlphaComponent(0.6)
toast.textColor = .white
toast.textAlignment = .center
toast.frame = CGRect(x: 20, y: self.view.frame.height - 100, width: self.view.frame.width - 40, height: 50)
toast.alpha = 0
self.view.addSubview(toast)
UIView.animate(withDuration: 0.5, animations: {
toast.alpha = 1
}) { _ in
UIView.animate(withDuration: 0.5, delay: 2, options: [], animations: {
toast.alpha = 0
}) { _ in
toast.removeFromSuperview()
}
}
}
}
API Reference
The API references for all the methods and events utilized in this guide are provided below.
Got a Question? Ask us on discord