docs/platform/integrations/push/push-activity-tracking.mdx
To enable activity tracking for Push channel notifications, Novu supports a manual integration approach for push notifications. Where your application captures and forwards push notification events to Novu. Once received, Novu processes and displays these events on the dashboard for a unified tracking experience.
The process involves a four-step data flow from your subscriber's device to Novu's servers:
Enable push activity tracking in your Novu dashboard and get the necessary credentials.
When push notifications are delivered or interacted with, your application must capture those events and forward them to your backend. The exact code implementation depends on the push provider that you use.
The goal is to capture the event and send a JSON payload to your backend. You must send these fields:
eventType: A string describing the event (for example, opened, clicked).eventId: The unique identifier for the notification, which Novu includes in the push payload as __nvMessageId.// Listen for notification interactions Notifications.addNotificationResponseReceivedListener(async (response) => { const eventData = { eventType: "opened", eventId: response.notification.request.content.data?.__nvMessageId, timestamp: new Date().toISOString(), actionIdentifier: response.actionIdentifier, content: { title: response.notification.request.content.title, body: response.notification.request.content.body, data: response.notification.request.content.data, }, // Optional device context deviceId: Constants.sessionId, platform: Platform.OS, }});
await fetch("https://your-api.com/api/notifications/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(eventData),
});
</Tab>
<Tab title="fcm">
```javascript
import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';
const trackNotificationOpen = async (remoteMessage) => {
const eventData = {
eventType: "opened",
eventId: remoteMessage?.data?.__nvMessageId,
timestamp: new Date().toISOString(),
content: {
title: remoteMessage?.notification?.title,
body: remoteMessage?.notification?.body,
},
deviceId: await messaging().getToken(),
platform: Platform.OS,
};
try {
await fetch("https://your-api.com/api/notifications/events", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(eventData),
});
} catch (err) {
console.log("Failed to track notification event", err);
}
};
// App opened from background
messaging().onNotificationOpenedApp(trackNotificationOpen);
// App opened from quit state
messaging()
.getInitialNotification()
.then((remoteMessage) => {
if (remoteMessage) {
trackNotificationOpen(remoteMessage);
}
});
OneSignal.setNotificationOpenedHandler((openedEvent) => { const { notification } = openedEvent;
const eventData = {
eventType: "opened",
eventId: notification.additionalData?.__nvMessageId,
timestamp: new Date().toISOString(),
content: {
title: notification.title,
body: notification.body,
},
deviceId: notification.notificationId,
platform: 'ios',
};
fetch("https://your-api.com/api/notifications/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(eventData),
});
});
</Tab>
</Tabs>
## Step 3: Forward events to Novu from your backend
Create an endpoint on your backend that receives the event data from your application and uses the Novu SDK to forward it to Novu.
<Tabs>
<Tab title="Node.js">
```typescript
import { Novu } from '@novu/api';
const novuClient = new Novu({ secretKey: process.env.NOVU_SECRET_KEY });
app.post('/api/notifications/events', async (req, res) => {
const response = await novuClient.activity.track({
environmentId: process.env.NOVU_ENVIRONMENT_ID,
integrationId: process.env.NOVU_INTEGRATION_ID,
requestBody: req.body,
});
res.status(200).json({ success: true, data: response });
});
novu_client = Novu(secret_key=os.getenv("NOVU_SECRET_KEY", ""))
@app.post("/api/notifications/events") async def track_push_event(req_body: dict): with novu_client as novu: response = novu.activity.track( environment_id=os.getenv("NOVU_ENVIRONMENT_ID", ""), integration_id=os.getenv("NOVU_INTEGRATION_ID", ""), request_body=req_body, ) return {"success": True, "data": response}
</Tab>
<Tab title="Go">
```go
import (
"context"
"os"
novugo "github.com/novuhq/novu-go"
"github.com/novuhq/novu-go/models/components"
)
s := novugo.New(novugo.WithSecurity(os.Getenv("NOVU_SECRET_KEY")))
res, err := s.Activity.Track(context.Background(), components.ActivityTrackRequestDto{
EnvironmentID: os.Getenv("NOVU_ENVIRONMENT_ID"),
IntegrationID: os.Getenv("NOVU_INTEGRATION_ID"),
RequestBody: eventData,
}, nil)
$sdk = novu\Novu::builder()->setSecurity(getenv('NOVU_SECRET_KEY'))->build(); $response = $sdk->activity->track( activityTrackRequestDto: new Components\ActivityTrackRequestDto( environmentId: getenv('NOVU_ENVIRONMENT_ID'), integrationId: getenv('NOVU_INTEGRATION_ID'), requestBody: $reqBody, ), );
</Tab>
<Tab title=".NET">
```csharp
using Novu;
using Novu.Models.Components;
var sdk = new NovuSDK(secretKey: Environment.GetEnvironmentVariable("NOVU_SECRET_KEY"));
var response = await sdk.Activity.TrackAsync(
activityTrackRequestDto: new ActivityTrackRequestDto() {
EnvironmentId = Environment.GetEnvironmentVariable("NOVU_ENVIRONMENT_ID"),
IntegrationId = Environment.GetEnvironmentVariable("NOVU_INTEGRATION_ID"),
RequestBody = reqBody,
});
Novu novu = Novu.builder().secretKey(System.getenv("NOVU_SECRET_KEY")).build(); var response = novu.activity().track() .body(ActivityTrackRequestDto.builder() .environmentId(System.getenv("NOVU_ENVIRONMENT_ID")) .integrationId(System.getenv("NOVU_INTEGRATION_ID")) .requestBody(reqBody) .build()) .call();
</Tab>
<Tab title="cURL">
```bash
curl -L -X POST 'https://api.novu.co/v1/activity/track' \
-H 'Content-Type: application/json' \
-H 'Authorization: ApiKey <NOVU_SECRET_KEY>' \
-d '{
"environmentId": "<NOVU_ENVIRONMENT_ID>",
"integrationId": "<NOVU_INTEGRATION_ID>",
"requestBody": {
"eventType": "opened",
"eventId": "<__nvMessageId>"
}
}'
Once these steps are completed, your application will send push notification engagement data to Novu. This gives you a complete, unified view of your notification performance in the Activity Feed.