|
| 1 | +--- |
| 2 | +title: Send Notifications (Neynar) |
| 3 | +description: Learn how to engage users through in-app notifications using Neynar |
| 4 | +--- |
| 5 | + |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +[**Neynar**](https://neynar.com/) is the easiest infrastructure platform for building Farcaster mini apps on Base and provides a simple way to: |
| 10 | + |
| 11 | +- manage approved notification tokens, no need to store on developer side |
| 12 | +- send notifications in a single API call, no need to batch |
| 13 | +- automate handling of notification permission revokes, and mini app "remove" events |
| 14 | +- target notifications to specific user cohorts |
| 15 | +- send notifications using the dev portal without having to write code |
| 16 | +- track notification analytics including open rates |
| 17 | + |
| 18 | +Mini app analytics will automatically populate in the Dev Portal dashboard once you use Neynar for notifications. |
| 19 | + |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | +- Neynar developer account -- sign up for free [here](https://neynar.com) |
| 23 | +- Neynar React SDK `@neynar/react` |
| 24 | +- Base App account |
| 25 | + |
| 26 | + |
| 27 | +## Enable Notifications |
| 28 | + |
| 29 | +<Steps> |
| 30 | +<Step title="Set up Notifications on Neynar"> |
| 31 | +The Neynar mini app events webhook URL is on the Neynar app page. Navigate to [dev.neynar.com/app](https://dev.neynar.com/app) and then click on the app. |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +</Step> |
| 37 | +<Step title="Add Webhook URL to Manifest"> |
| 38 | +Set the Neynar frame events URL as the `webhookUrl` in the Frame Config object inside the manifest. Here's an example manifest: |
| 39 | + |
| 40 | +```json highlight={14} |
| 41 | +{ |
| 42 | + "accountAssociation": { |
| 43 | + "header": "eyJmaWQiOjE5MSwidHlwZSI6ImN1c3RvZHkiLCJrZXkiOiIweDNhNmRkNTY5ZEU4NEM5MTgyOEZjNDJEQ0UyMGY1QjgyN0UwRUY1QzUifQ", |
| 44 | + "payload": "eyJkb21haW4iOiIxYmNlLTczLTcwLTE2OC0yMDUubmdyb2stZnJlZS5hcHAifQ", |
| 45 | + "signature": "MHg1ZDU1MzFiZWQwNGZjYTc5NjllNDIzNmY1OTY0ZGU1NDMwNjE1YTdkOTE3OWNhZjE1YjQ5M2MxYWQyNWUzMTIyM2NkMmViNWQyMjFhZjkxYTYzM2NkNWU3NDczNmQzYmE4NjI4MmFiMTU4Y2JhNGY0ZWRkOTQ3ODlkNmM2OTJlNDFi" |
| 46 | + }, |
| 47 | + "frame": { |
| 48 | + "version": "4.2.0", |
| 49 | + "name": "Your Frame Name", |
| 50 | + "iconUrl": "https://your-frame-domain.com/icon.png", |
| 51 | + "splashImageUrl": "https://your-frame-domain.com/splash.png", |
| 52 | + "splashBackgroundColor": "#f7f7f7", |
| 53 | + "homeUrl": "https://your-frame-domain.com", |
| 54 | + "webhookUrl": "https://api.neynar.com/f/app/3c274018-6402-4a47-96bbg-1fea72afc408/event" |
| 55 | + } |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +<Warning> |
| 60 | +Frame manifest caching: Farcaster clients might have your mini app manifest cached and would only get updated on a periodic basis. |
| 61 | +</Warning> |
| 62 | + |
| 63 | +<Tip> |
| 64 | +If you're using Farcaster to test, you can go to their Settings > Developer Tools > Domains, put in your Frame URL and hit the Check domain status to force a refresh. |
| 65 | +</Tip> |
| 66 | + |
| 67 | +</Step> |
| 68 | +</Steps> |
| 69 | + |
| 70 | +## Prompt Users to Add Your App |
| 71 | +<Steps> |
| 72 | +<Step title="Install the Neynar React package"> |
| 73 | + |
| 74 | +You will use the Neynar React package to access the Mini App components. |
| 75 | + |
| 76 | +```shell |
| 77 | +npm install @neynar/react |
| 78 | +``` |
| 79 | +</Step> |
| 80 | +<Step title="Wrap your app with the MiniAppProvider component"> |
| 81 | + |
| 82 | +Wrap your app with the `MiniAppProvider` component to enable Mini App functionality: |
| 83 | + |
| 84 | +```javascript app/app.tsx |
| 85 | +import { MiniAppProvider } from '@neynar/react'; |
| 86 | + |
| 87 | +export default function App() { |
| 88 | + return ( |
| 89 | + <MiniAppProvider> |
| 90 | + {/* Your app components */} |
| 91 | + </MiniAppProvider> |
| 92 | + ); |
| 93 | +} |
| 94 | +``` |
| 95 | +</Step> |
| 96 | + |
| 97 | +<Step title="Prompt users to add your Mini App"> |
| 98 | + |
| 99 | +Use the `useMiniApp()` hook to prompt users to add your Mini App. |
| 100 | + |
| 101 | +Neynar will manage all mini app add/remove and notifications enabled/disabled events delivered on this events webhook. |
| 102 | + |
| 103 | +The snippet below checks if `result.added` is **true** and `result.notificationDetails` is a valid object. |
| 104 | + |
| 105 | +```javascript app/page.tsx |
| 106 | +import { useMiniApp } from '@neynar/react'; |
| 107 | + |
| 108 | +export default function HomePage() { |
| 109 | + const { isSDKLoaded, addMiniApp } = useMiniApp(); |
| 110 | + |
| 111 | + const handleAddMiniApp = async () => { |
| 112 | + if (!isSDKLoaded) return; |
| 113 | + |
| 114 | + const result = await addMiniApp(); |
| 115 | + if (result.added && result.notificationDetails) { |
| 116 | + // Mini app was added and notifications were enabled |
| 117 | + console.log('Notification token:', result.notificationDetails.token); |
| 118 | + } |
| 119 | + }; |
| 120 | + |
| 121 | + return ( |
| 122 | + <button onClick={handleAddMiniApp}> |
| 123 | + Add Mini App |
| 124 | + </button> |
| 125 | + ); |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +</Step> |
| 130 | +</Steps> |
| 131 | + |
| 132 | +## Send Notifications to Users |
| 133 | + |
| 134 | +Notifications can be broadcast to all your mini app users with notifications enabled or to a limited set of FIDs. Notifications can also be filtered so that only users meeting certain criteria receive the notification. |
| 135 | + |
| 136 | + |
| 137 | +The [Neynar dev portal](https://dev.neynar.com) offers the same functionality as the API for broadcasting notifications. Navigate to your app and click the "Mini App" tab. Once your mini app is configured with your Neynar webhook URL and users have enabled notifications for your mini app, you'll see a "Broadcast Notification" section with an expandable filters section. |
| 138 | + |
| 139 | + |
| 140 | +### Option 1: Neynar UI |
| 141 | + |
| 142 | +Notifications can easily be sent using the Neynar Dev Portal. |
| 143 | + |
| 144 | +<Steps> |
| 145 | +<Step title="Log in to the Neynar Dev Portal"> |
| 146 | +https://dev.neynar.com/home |
| 147 | +</Step> |
| 148 | + |
| 149 | +<Step title="Select your target App"> |
| 150 | + |
| 151 | + |
| 152 | +</Step> |
| 153 | +<Step title="Navigate to Mini App tab"> |
| 154 | + |
| 155 | +</Step> |
| 156 | + |
| 157 | +<Step title="Fill in Notification details"> |
| 158 | + |
| 159 | +<Tip>The `target_fids` parameter is the starting point for all filtering. Pass an empty array for `target_fids` to start with the set of all FIDs with notifications enabled for your app, or manually define `target_fids` to list specific FIDs.</Tip> |
| 160 | + |
| 161 | +</Step> |
| 162 | + |
| 163 | +<Step title="Click the Broadcast button"> |
| 164 | +Once you have filled in the notification details and applied any filtering, broadcast your notification by clicking the broadcast button at the bottom of the page. |
| 165 | +</Step> |
| 166 | +</Steps> |
| 167 | + |
| 168 | + |
| 169 | +### Option 2: API |
| 170 | + |
| 171 | +You can programmatically send notifications using the Neynar API. This gives you full control over targeting and filtering users. |
| 172 | + |
| 173 | +<Steps> |
| 174 | +<Step title="Install the Neynar Node.js SDK"> |
| 175 | + |
| 176 | +Install the [@neynar/nodejs-sdk](https://github.com/neynarxyz/nodejs-sdk) package: |
| 177 | + |
| 178 | +```shell |
| 179 | +npm install @neynar/nodejs-sdk |
| 180 | +``` |
| 181 | +</Step> |
| 182 | + |
| 183 | +<Step title="Create a notification sending function"> |
| 184 | + |
| 185 | +Create a reusable function to send notifications with targeting and filtering capabilities: |
| 186 | + |
| 187 | +```javascript lib/sendNotification.js |
| 188 | +import { NeynarAPIClient } from "@neynar/nodejs-sdk"; |
| 189 | + |
| 190 | +const client = new NeynarAPIClient(process.env.NEYNAR_API_KEY); |
| 191 | + |
| 192 | +/** |
| 193 | + * Send a notification to mini app users |
| 194 | + * @param {number[]} targetFids - Array of FIDs to target (empty array = all users with notifications enabled) |
| 195 | + * @param {Object} filters - Optional filters to narrow down recipients |
| 196 | + * @param {Object} notification - Notification content and target URL |
| 197 | + */ |
| 198 | +export async function sendNotification(targetFids, filters, notification) { |
| 199 | + try { |
| 200 | + const response = await client.publishFrameNotifications({ |
| 201 | + targetFids, |
| 202 | + filters, |
| 203 | + notification, |
| 204 | + }); |
| 205 | + |
| 206 | + return { |
| 207 | + success: true, |
| 208 | + data: response, |
| 209 | + }; |
| 210 | + } catch (error) { |
| 211 | + console.error("Failed to send notification:", error); |
| 212 | + return { |
| 213 | + success: false, |
| 214 | + error: error.message, |
| 215 | + }; |
| 216 | + } |
| 217 | +} |
| 218 | +``` |
| 219 | +</Step> |
| 220 | + |
| 221 | +<Step title="Send notifications"> |
| 222 | + |
| 223 | +Use the function to broadcast notifications with advanced filtering criteria: |
| 224 | + |
| 225 | +```javascript |
| 226 | +import { sendNotification } from './lib/sendNotification'; |
| 227 | + |
| 228 | +// Define target FIDs (empty array targets all users with notifications enabled) |
| 229 | +const targetFids = []; |
| 230 | + |
| 231 | +// Define filters to narrow down recipients |
| 232 | +const filters = { |
| 233 | + exclude_fids: [420, 69], // Exclude specific FIDs |
| 234 | + following_fid: 3, // Only send to users following this FID |
| 235 | + minimum_user_score: 0.5, // Only send to users with score >= this value |
| 236 | + near_location: { // Only send to users near a specific location |
| 237 | + latitude: 34.052235, |
| 238 | + longitude: -118.243683, |
| 239 | + radius: 50000, // Distance in meters (optional, defaults to 50km) |
| 240 | + } |
| 241 | +}; |
| 242 | + |
| 243 | +// Define notification content |
| 244 | +const notification = { |
| 245 | + title: "🪐", |
| 246 | + body: "It's time to savor farcaster", |
| 247 | + target_url: "https://your-frame-domain.com/notification-destination", |
| 248 | +}; |
| 249 | + |
| 250 | +// Send the notification |
| 251 | +const result = await sendNotification(targetFids, filters, notification); |
| 252 | + |
| 253 | +if (result.success) { |
| 254 | + console.log("Notification sent successfully:", result.data); |
| 255 | +} else { |
| 256 | + console.error("Failed to send notification:", result.error); |
| 257 | +} |
| 258 | +``` |
| 259 | + |
| 260 | +<Tip> |
| 261 | +The `target_fids` parameter is the starting point for all filtering. Pass an empty array to target all users with notifications enabled, or specify FIDs to target specific users. |
| 262 | +</Tip> |
| 263 | +</Step> |
| 264 | +</Steps> |
| 265 | + |
| 266 | +Additional documentation on the API and its body parameters can be found at [publish-frame-notifications](https://docs.neynar.com/reference/publish-frame-notifications). |
0 commit comments