Real-time advertising and updates

PubNub enables real-time analytics and automated customer-behavior-driven decisioning for live sports applications, creating dynamic experiences that adapt instantly to fan engagement and how they interact with your application.

By the end of this document, you will:

  • Learn how to implement automated emoji upgrades based on user behavior
  • Get to know how to serve dynamic ads based on user sentiment
  • Understand how to trigger dynamic polls based on user reactions and engagement
  • Discover how to track real-time analytics and make automated content decisions

How PubNub helps

Role in the solutionPubNub feature (click to learn more!)
  • Track user engagement in real time
Pub/Sub
  • Trigger polls and surveys based on user engagement
  • Upgrade emojis based on reaction thresholds
  • React to user behavior in real-time to provide targeted ads
PubNub Illuminate

Use case overview

The Live Events demo shows how you can respond to user behavior in real-time. By targeting specific milestones in your app, you automate actions to enhance the user experience and monetize engagement by unlocking additional features for active users or offering incentives before they disengage.

The demo will take action based on the following user behavior:

  • Triggers: The demo uses emoji reactions (😡, 🎉) as triggers, but you could also trigger actions based on chat mentions, poll participation, or any custom user behavior you want to track.

    More about triggers

    For information on automatically triggering polls based on user reactions, refer to Automated polling.

  • Processing: The demo aggregates emoji reactions over a 60-second window, but you could also process events immediately (like responding to a mention) or implement custom processing logic based on your needs.

  • Actions: When triggers are processed, the demo shows automated actions like displaying a custom poll ("Which team is playing the dirtiest?"), but you could also trigger emoji upgrades, dynamic ads, or any custom response you define.

See it in action

Notice in the clip below how the 🔥 emoji changes to 😎 and the "Time to unwind?" ad appears when the user gets increasingly frustrated.


Basic setup for automated decisioning

The Live Events demo uses PubNub Illuminate to trigger emoji upgrades, polls, and dynamic ads based on user behavior.

PubNub Illuminate is designed to enhance real-time applications by providing advanced analytics and automated decision-making capabilities without changing the application code.

It allows product managers to create dynamic user experiences by reacting to user engagement and behavior in real-time. With Illuminate, you can trigger actions such as polls, surveys, and targeted advertisements based on user interactions, ensuring that content is always relevant and engaging.

Before you can leverage the powerful features of PubNub Illuminate for real-time analytics and automated decision-making, ensure the following prerequisites are met:

PrerequisiteDescription
PubNub account
You must have an active PubNub account. If you don't have one, you can sign up on the Admin Portal.
Any PubNub SDK
Your app must use a PubNub SDK. This is essential for connecting your app to the PubNub network and utilizing Illuminate's capabilities.
Illuminate subscription
Ensure that your PubNub pricing plan includes Illuminate. For more information, refer to PubNub Pricing.
SDK configuration

You can use any PubNub SDK to implement this solution. For optimal performance and security:

  • Use unique user IDs for each user, but reuse it for different client devices ( mobile, tablet, via browser) of the same user.
  • Keep your publish and subscribe keys secure.
  • Consider using environment variables for sensitive data.

For more information on available configuration options, refer to the Configuration documentation of the SDK you're using. The Live Events demo app uses the JavaScript SDK via the JavaScript Chat SDK, which provides chat-specific methods as well as the core JavaScript SDK operations, but that's not important to illustrate how automated decisioning works.

Emoji upgrades and dynamic ads

In the Live Events demo, there are two realtime decisions triggered by user behavior:

  • Emoji upgrades - when a user taps an emoji more than 10–20 times in 60 seconds, Illuminate triggers an upgrade to a more expressive emoji, for example: 😢 upgrades to 😭 or 😡 to 🤬.
  • Dynamic ads - when a user taps the 😡 emoji more than 20 times in 60 seconds, Illuminate triggers a "Time to unwind?" ad because the user is clearly frustrated.

This shows how an app can take custom actions based on user behavior in real-time.

Track emoji taps

When a user taps an emoji (e.g., 😡), a message is published to a dedicated channel (e.g., game.stream-reactions) with the following data:

async function emojiClicked(emoji) {
if (!chat) return
await chat.sdk.publish({
message: { text: `${emoji}`, type: 'reaction' },
channel: streamReactionsChannelId
})
}

Depending on the emoji tapped, the app reacts differently. In this case, we use the 😡 emoji tap as an indicator of frustration, but you can use any behavior you want to track and react to. When the user clicks other emojis, the app recognizes the behavior and triggers the appropriate action - changing the emoji to a heart or upgrading the emoji.

Configure Illuminate

Now that we have a steady stream of data on the game.stream-reactions channel, we can configure Illuminate to trigger the emoji upgrade based on the user's behavior.

Illuminate consists of these modules:

  • Business Object – how you get data into Illuminate. Business Objects are containers for capturing data from the selected apps and keysets. You can add and define (data fields, create metrics) with the desired aggregation, and activate Business Objects to start the data capture process.
  • Decision – where you take action on the metrics you've created. You can do that by defining rules with conditions to be met, and actions triggered whenever these rules are met.
  • Dashboard – where you visualize the metrics you've created in Business Objects and actions executed in Decisions through charts and dashboards (collections of charts).

Illuminate — building blocks

Let's start with creating a Business Object.

Create a Business Object

In Illuminate, the first thing to do is create a business object. You can see what the business object looks like in detail in the Demo Admin portal account here.

Business Object

When you create a new business object, you must attach it to an app and keyset and map the data fields to the events you want to track. For detailed information on creating business objects, refer to Create Business Object. In the meantime, inspect the business object that the Live Events demo uses.

Data fields

Field NameMapped FromTypeDescription
Reaction
$.message.body.text
String
This is the emoji or user reaction content. It captures the emoji tapped by the user, providing insight into user interactions and preferences.
Channel
$.message.channel
String
This captures the channel name on which the message was sent.
MessageType
$.message.body.type
String
This is always reaction in the Live Events demo, but if you are sending multiple message types on the same channel, you can filter them by this field.

You can use the data fields for conditional logic, but more on that later. For now, let's focus on what we want to track.

Create metrics

By defining specific metrics, product managers can tailor the user experience to be more responsive and engaging, ensuring that the application reacts to user behavior in meaningful ways. For detailed information on creating metrics, refer to Create Metric.

Metric

In the Live Events application, the Count of Reactions in a Minute metric tracks how many user reactions (emoji taps) occur in a specific channel, filtered by message type and evaluated every minute. It's used to power decisions such as emoji upgrades, dynamic ads, and live polls.

FieldValueDescription
Name
Count of Reactions in a Minute
Human-readable name for the metric, used in dashboards and decisions.
Function
COUNT
Aggregation function that counts the number of messages matching the filter during each evaluation period.
Measure
None
No custom numeric field is being measured (e.g., summing a value). The metric just counts the number of matching events.
Period
1 minute
The aggregation window. Messages are counted over a rolling one-minute period.
Filter
Channel Equals game.stream-reactions MessageType Equals reaction
Filters incoming PubNub messages to only include messages of type reaction sent on the game.stream-reactions channel.
Dimensions
Reaction, Channel, MessageType
Fields used to group the metric data. Allows the count to be tracked separately for each unique emoji (reaction), channel, and message type.
Used in Decisions
Emoji Upgrades & Ads
This metric triggers downstream Illuminate Decisions that perform actions like upgrading emojis or launching dynamic content (e.g., polls).
Used in Dashboards
Live Events
This metric is also used in the Showcase: Live Events dashboard for monitoring and visualizing reaction activity in real-time.

To start capturing and storing the data, you must activate the business object.

Activate the business object

When you click the Activate button, Illuminate starts capturing the emoji taps until you deactivate or delete the business object. You can't add or remove data fields once you've activated a business object, but you can add a metric to it.

Data you defined in business objects and subsequently captured are housed in a single database for 90 days.

With the business object that is configured and active, you can create a decision or a dashboard.

icon

Before you activate


Create a decision

Decisions are the core of Illuminate. They are triggered by metrics and contain rules that define the conditions for actions to be executed. You can see the decision in detail in the Demo Admin portal account here.

icon

More on decisions


The Live Events demo has a single decision to trigger an emoji upgrade when a user taps any emoji more than the specified number of times (with one exception) in a minute and an ad when a user taps the 😡 emoji more than 20 times in one minute.

Decision

Each decision must have at least one associated condition and action. The Live Events demo has three actions:

ActionDescription
Showcase: Live Event Upgrade Emoji to Default
Upgrades the emoji to a more expressive one.
Showcase: Live Event Upgrade Emoji to Heart
Upgrades the upgraded emoji to a heart. As opposed to the Showcase: Live Event Upgrade Emoji to Default action, this action can override the emoji in the client app code. That's the exception we mentioned earlier.
Showcase: Live Event Show Dynamic Ad
Displays a dynamic ad.

Live Event Upgrade Emoji to Default

The Showcase: Live Event Upgrade Emoji to Default action upgrades the emoji to a more expressive one when the user taps the emoji more than the specified number of times in a minute.

In the Live Events demo, this is triggered when the user taps any emoji more than 20 times in one minute. This action publishes a message to the illuminate-upgrade-reaction channel with the following payload:

{
"emoji": "${Reaction}",
}

The emoji is defined as ${Reaction} because, in your Illuminate metric, you map incoming fields from PubNub messages to named fields so you can use them later. Remember when we mapped reaction to $.message.body.text during the Create a Business Object step? This is how we can use the actual emoji tapped by the customer in the Illuminate decision.

How the demo handles emoji upgrades

In the demo, Illuminate doesn't publish upgraded emojis. Instead, it notifies the client that the emoji has been upgraded by publishing a message, and the client handles the display using an emojiMap object that maps emojis to their upgraded versions. You can find more details on the demo's implementation in Listen for triggers and react.

Illuminate is flexible and you can configure it to handle emoji upgrades in different ways, like directly publishing the upgraded emoji, or triggering any other custom action you define.

Live Event Upgrade Emoji to Heart

The Showcase: Live Event Upgrade Emoji to Heart action upgrades the 😮 emoji to a heart.

In the Live Events demo, this is triggered when the user taps the 😮 emoji more than 20 times in one minute. This action publishes a message to the illuminate-upgrade-reaction channel with the following payload:

{
"emoji": "${Reaction}", // in this case, ${Reaction} == 😮
"replacementEmoji": "❤️"
}
Value of the emoji key

The actual value of the emoji key is ${Reaction}, but in this case, the update to the ❤️ emoji only happens when the user taps the 😮 emoji because of the condition in the decision.

This is a simple example, but it shows how non-technical staff can use Illuminate to change the behavior of the app without writing any code.

As opposed to the Showcase: Live Event Upgrade Emoji to Default action, Illuminate does publish the upgraded emoji to the game.stream-reactions channel in this case. Even though, it is still the responsibility of the client to display the upgraded emoji, you can use Illuminate to override the emoji in the app without modifying the client application.

Live Event Show Dynamic Ad

The Showcase: Live Event Show Dynamic Ad action displays an advert when the user taps the 😡 emoji in a show of frustration.

In the Live Events demo, this is triggered when the user taps the 😡 emoji more than 20 times in one minute. This action publishes a message to the illuminate-show-ad channel with the following payload:

{
"adId": 3,
"clickPoints": 12
}
FieldTypeDescription
adId
Integer
Identifies which dynamic ad to display in the client UI.
clickPoints
Integer
The number of points awarded when the user clicks the ad providing a reward loop for interaction and encouraging engagement.

Like with the emojis, Illuminate doesn't actually display the ad. It only notifies the client that the ad should be displayed by publishing a message and the client is responsible for displaying the ad accordingly. For more information, refer to Listen for triggers and react.

How the demo handles ads

Although these values (3 and 12) are hardcoded in the demo, they could be dynamic. For example, you could create a condition in the decision that the adId to show can change based on how many times the emoji is clicked.

Listen for triggers and react

Thus far, we've established that Illuminate consumes the data from your app and makes decisions based on the data. Now, let's see how the app reacts to the data that Illuminate sends.

Live Events demo implementation

The demo is designed to be easy to set up and understand, so it uses hard-coded values and PubNub messaging for all communication between Illuminate and the client application.

In a production environment, you would typically have a server that sits between Illuminate and the client app, listening for either PubNub messages or webhooks from Illuminate, and dynamically adjusting the content to show or targeting specific users to receive the upgraded emoji.

The application listens for real-time triggers from Illuminate by subscribing to the relevant PubNub channels. The Live Events demo handles messages on the game.stream-reactions and illuminate-show-ad channels and reacts to them in real-time.

When Illuminate triggers an emoji upgrade or ad, it can take various actions. In this demo, it publishes a message to the game.stream-reactions or illuminate-show-ad channels (we configured this in the Create a decision step), but it could also trigger webhooks, send emails, or perform any other custom action you define. Depending on which channel the message is published to, the app reacts differently.

The StreamWidget component subscribes to the illuminate-upgrade-reaction channel and calls the upgradeEmoji function when a message is received on that channel. It is in that method that the current emoji to upgraded emoji mapping is handled. However, if you remember the Live Event Upgrade Emoji to Heart decision, Illuminate actually publishes the upgraded emoji to the game.stream-reactions channel when the user taps the 😮 emoji more than 20 times in one minute. In this case, the emojiMap is not used and the app displays the ❤️ emoji sent by Illuminate.

//  Illuminate: Upgrade emoji
const illuminateEmojiChannel = chat.sdk.channel(illuminateUpgradeReaction)
const illuminateEmojiSubscription = illuminateEmojiChannel.subscription({
receivePresenceEvents: false
})
illuminateEmojiSubscription.onMessage = messageEvent => {
// Received a request to upgrade a specific emoji
const emojiToUpgrade = messageEvent.message.emoji
const replacementEmoji = messageEvent.message.replacementEmoji
upgradeEmoji(emojiToUpgrade, replacementEmoji)
}
illuminateEmojiSubscription.subscribe()
return () => {
reactionsSubscription.unsubscribe()
occupancySubscription.unsubscribe()
show all 47 lines

Dynamic ads are managed by the CommonMessageHandler component. It keeps a dynamicAd state and listens to the dynamicAdChannelId channel. When a message is received, CommonMessageHandler processes it and calls setDynamicAd. If setDynamicAd is given an ad object, the AdvertsOfferWidget is shown. If setDynamicAd is called with null, the ad is removed from view.


In the Live Events demo, the CommonMessageHandler component is responsible for processing messages from Illuminate and managing the application state.

export async function CommonMessageHandler(
isGuidedDemo,
messageEvent,
onSetNotification,
onSetDynamicAd
) {
// push notifications code, irrelevant to this example
} else if (messageEvent.channel === dynamicAdChannelId) {
// Handle dynamic ads
const adId = messageEvent.message.adId;
const clickPoints = messageEvent.message.clickPoints;
if (adId && clickPoints) {
onSetDynamicAd({ adId: adId, clickPoints: clickPoints });
} else {
onSetDynamicAd(null);
show all 20 lines

The actual display of the ad is handled by the AdvertsOfferWidget component, which looks up the ad image source from a constant array of ads. If the ad isn't found, it shows a placeholder image.

By leveraging PubNub Illuminate, you can automate real-time decisioning in your applications that respond instantly to engagement and sentiment. The best thing about it is that you don't need to change your app code to do it. Once set up in the app, you can change the decision rules and actions directly in Illuminate.

Last updated on