与 Novu 一起打造一款热门的全新外卖应用
太长不看
太长不看
在本教程中,我们将创建一个工具来管理外卖应用程序的通知系统。为此,我们将利用 Novu 的开源通知基础架构 、我们自定义的平台以及 PostMark。
加入 ConnectNovu 黑客马拉松
展示你的技能,突破创新界限,结识志同道合的社区成员。
ConnectNovu Hackathon 是一项专注于通知功能的全球性活动。如果您喜欢研究应用内通知、短信、推送通知、电子邮件和聊天功能,那么这里就是您的理想之选!
你准备好打造下一个伟大产品了吗?🚀
开球
我们都喜欢外卖应用程序的新时代。无需打电话,几分钟就能在手机上完成下单,支付高额配送费,然后就可以满怀期待地等待美食送到家门口。
但在这个过程中,这些外卖应用会让你随时了解整个流程——从下单到包裹送达。但要做到这一点,你需要一个强大的通知系统来处理。
在本教程中,我们将学习如何使用功能强大的开源通知基础架构 Novu 为食品配送应用程序创建通知管理系统。
如果你想直接查看本教程的源代码,请点击这里。
投身商界
在本教程中,我们将从一个名为Foody 的简单应用开始。我们将使用 Nuxt 和 Supabase 创建项目,但您也可以使用任何您喜欢的 JavaScript 框架。您还需要 Node.js 的 LTS 版本。
通常,我们会期望在任何电子商务服务中收到一系列通知,外卖系统也不例外。对于 Foody,我们至少需要以下几种类型的通知:
- 客户接待通知:欢迎和感谢用户。
- 服务特定通知:- 订单提交、发货状态、反馈请求、促销活动。
- 法律和安全更新通知:条款和隐私等。
让我们看看 Novu 如何在食品配送服务环境中处理这些通知。
项目启动
我们需要注册一个 Novu 账号,然后开始设置我们的项目。
之后,我们需要至少设置一个配送服务提供商。该配送服务提供商将用于管理我们应用内的所有通知。请前往集成商店查看我们的选项。
截至撰稿时,Novu 支持三种通知渠道:电子邮件、短信和应用内通知中心。如果您想创建除已提供渠道之外的其他通知提供程序,请参阅其文档。
我们将使用 Postmark 为Foody设置一个新的服务提供商。让我们开始吧。
设置 PostMark
首先,我们需要一个PostMark 账户。注册完成后,我们需要验证发件人身份,如果服务器 API 令牌尚不存在,则需要创建一个新的令牌。
返回 Novu 集成商店 页面,点击 Postmark 连接,填写 表单中的“发件人”信息,并将发件人设置Server API token 为 Postmark 上已验证的发件人。最后,提供发件人信息 ,将发件人切换为“激活”状态,然后点击 连接 按钮。API Keyfrom emailsender name
在 Novu 上创建通知
要在 Novu 上创建新通知,请点击 “通知” 页面,然后点击右上角的 “新建”Notification Name按钮。填写新模板的通知设置,包括提供通知 类型Notification Description、通知宽度和 Notification Group通知类型(默认设置 为“常规”) 。
发送欢迎通知
对于Foody,我们将设置一封客户欢迎电子邮件,以演示如何在 Novu 中设置通知。填写上图中的字段,设置 Notification Name to welcome-new-user和 Notification Description to Notification for welcoming newly registered users。
前往新通知的“工作流编辑器”选项卡添加步骤。在本例中,我们希望发送一封欢迎客户的电子邮件通知,然后接收该客户的应用内管理员控制面板通知。因此,在此页面上,将 电子邮件 步骤拖到画布上,然后再 拖放应用内 步骤。
选择 画布中当前的电子邮件步骤并编辑模板。您可以使用可视化模板编辑器,也可以为电子邮件渠道编写自定义标记。我们将使用模板编辑器:
编辑器右侧的 “步骤变量”部分 列出了我们在 Handlebars 邮件模板中使用的变量{{}}。这些变量将由通过 Novu 触发器发送的已提交邮件有效负载填充。您可以在完成后预览和测试创建的电子邮件通知,以便进行故障排除。
返回工作流程编辑器,选择 应用内 步骤并编辑其模板:
在用户帐户验证之后调用此触发器,以在 Foody 中触发此通知。
将 Novu 集成到 Foody 中
如果您按照本教程提供的 Nuxt 应用进行操作,则服务器 API 端点文件中已设置了以下逻辑 /server/api/register-notifications-subscriber.js。此通知有两个用途,第一个用途是将应用用户注册为 Novu 通知订阅者,第二个用途是发送欢迎电子邮件。
// dependency imports
export default defineEventHandler(async (event) => {
// variable declarations
// Send welcome notification to new user
const [firstName, lastName] = user.user_metadata.full_name.split(" ");
await novu.trigger('welcome-new-user', {
to: {
subscriberId: user.id,
email: user.user_metadata.email,
firstName,
lastName,
phone: user.user_metadata.phone,
},
payload: {
firstName
},
});
// other code
})
尽管我们没有在邮件模板中使用这些数据,但我们仍然在上述代码中尽可能多地向触发器提供了订阅者数据。为什么呢?因为当触发器被调用时,Novu 会将数据更新插入到新的订阅者列表中;如果列表中不存在订阅者,则会创建一个新的订阅者。
要显式创建新订阅者,请使用以下命令:
await novu.subscribers.identify(user.id, {
email,
firstName,
lastName,
phone: user.user_metadata.phone,
});
注册了一些用户之后,访问 Novu 控制面板的“活动动态”部分时,我们应该会看到以下内容:
活动动态会监控与 Novu 项目相关的所有外发消息。它可以监控活动并发现提供商或渠道可能存在的问题。
使用 Novu 发送订单特定通知
现在我们已经了解了如何向 Foody 用户发送欢迎邮件,接下来让我们再来处理实际订单!
发送订单确认信息
和其他外卖应用一样,我们希望让顾客随时了解订单状态。因此,接下来我们需要设置一个通知功能,在顾客下单后发送确认信息。
按照前面的步骤创建一个新的通知,设置 Notification Name 到 "order-confirmation" 和 Notification Description到 "Notifying users on order placement"。
本次通知中,我们希望发送一份用户购买菜品的列表。因此,编写邮件模板的合适方法是使用以下自定义标记:
<div>
Hello {{subscriber.firstName}},
</div>
<div style="padding: 4px">
You successfully placed order number #{{orderNumber}}.
</div>
<ul style="padding: 4px">
{{#each dishes }}
<li>{{count}} x {{name}} </li>
{{/each}}
</ul>
<div style="padding: 4px">
Delivery Fees: {{deliveryFee}}$
</div>
<div style="padding: 4px; font-weight: 800">
Total: {{totalFee}}$
</div>
<div style="padding: 4px">
Please notify us if any dish is out of order.
</div>
我们可以看到上面的模板有两个新特点,它与我们之前创建的电子邮件模板有所不同。
首先,我们有 subscriber.firstName 变量。Novu 使用特定的订阅者数据模型来管理应用程序的用户,这使得 API 能够管理通知流程的不同方面,同时提供一个便捷的通知触发接口。该 subscriber.firstName 变量来自 订阅者对象的用户数据 点,因此可以将其放置在通知模板中。我们还可以从 用户数据点中获取其他数据, 例如 lastName …… avatar
与之前的模板不同的是,第二个不同之处在于数组的遍历 dishes 。这得益于 Handlebars#each辅助函数。我们还可以 使用#if Handlebars 条件辅助函数,我们将在后续的通知章节中演示它的用法。
要使用创建的模板向我们的 Foody 客户发送订单确认通知,请添加以下触发器:
// imports and global functions
export default defineEventHandler(async (event) => {
// variable declarations
// order creation logic providing us with orderDetails variable
await novu.trigger('order-confirmation', {
to: {
subscriberId: user.id,
email: user.user_metadata.email
},
payload: {
dishes: order.dishes,
orderNumber: orderDetails.order_number,
deliveryFee: order.deliveryFee,
totalFee: order.totalFee
},
});
// other code
})
发送配送状态通知
为了让客户随时了解订单状态,我们需要通知他们订单的配送状态变更。请创建一个新的 delivery-status 通知,并使用以下代码作为模板:
<div>
Hello {{subscriber.firstName}},
</div>
<div style="padding: 4px">
You order #{{orderNumber}} has been {{status}}.
</div>
<div style="padding: 4px">
Click the following link to give us a feedback of your order.
{{#if delivered}}
<p>
<a href="{{feedbackUrl}}" target="_blank" style="padding: 2px">
Give us feedback
</a>
</p>
{{/if }}
</div>
配送状态通知可以包括“订单已取走”、“订单已送达”等。订单送达后, #if 我们还可以借助车把助手向用户发送链接,以便用户提供配送反馈。
我们为Foody创建的最后一条基于订阅者的通知 是反馈感谢通知。由于这条通知比前两条通知简单,我们可以使用模板编辑器来创建它。
以下代码可用作应用内通知的触发器:
// imports
export default defineEventHandler(async (event) => {
// Declarations and user feedback database-submission logic
await novu.trigger('feedback-appreciation', {
to: {
subscriberId: user.id,
email: user.email
},
payload: {
firstName
},
});
return {
message: 'Appreciated user!',
}
})
使用 Novu Topics 发送批量订阅通知
如果我们需要向一组客户或所有客户批量发送通知该怎么办?例如,我们希望批量发送促销、折扣、服务更新以及条款和服务变更等通知。如何在不进行成本高昂的数据循环处理的情况下实现这一点?
Novu 通过主题功能解决了这一难题 。Novu 主题功能允许我们根据自定义的任何条件向一组用户发送批量通知。借助主题功能,我们可以根据用户的兴趣、订阅或其他任何可确定的属性向他们发送多封电子邮件。
在我们的场景中,我们可能希望根据顾客经常购买的菜品向他们发送促销和折扣通知。例如,如果我们把顾客购买某道菜的次数视为他们喜欢这道菜,我们会将他们添加到一个包含喜欢这道菜的顾客的话题中。我们可以将这样的话题命名为“喜欢这道菜的顾客” customers:favorite:dish_id。
在我们的应用程序中添加此类功能,将使我们能够针对部分用户群体投放定向广告,而不是依赖广撒网式的客户互动方式。
创建 Novu 主题
现在我们已经了解了 Novu 中有哪些主题,接下来让我们学习如何创建一个主题。
我们将为Foody创建一个主题 ,用于根据客户的购买行为向他们发送促销通知,就像我们之前讨论的那样。但在为主题分配订阅者之前,我们需要先创建该主题。
在我们的外卖服务场景中,每当向应用程序数据库添加一道菜品时,都必须创建一个主题。以下创建主题的代码最好放在向数据库提交新菜品的逻辑之后:
// Dish data submission logic
const result = await novu.topics.create({
key: "customers:favorite:" + newDishData.id,
name: "Customers that like " + newDishData.name
});
请记住,Novu 主题键应该是唯一的,并且一旦创建就不能更改。
添加新订阅者并发送通知
要向某个主题添加新的订阅者,我们需要使用以下 addSubscriber() 方法:
// Order placement logic
// When customer fulfils criteria to be added to topic involving dish[0]
const result = await novu.topics.addSubscribers(
'customer:favorites:' + order.dishes[0].id,
{
subscribers: [user.id]
})
在应用内部,这段代码应该紧接在订单提交代码之后调用。符合条件的用户将被添加到相应的主题中。
创建主题并添加订阅者后,下一步是向订阅者发送通知。首先,为该主题创建一个通知,例如“主题已创建 dish-based-promotional-notification”。别忘了也为此添加一个模板!
最后,创建一个发送通知的触发器。Novu 的主题通知触发器与用于向单个订阅者发送通知的触发器相同。区别在于,在字段中 to ,我们传递的不是单个订阅者的身份信息,而是一个主题数组,我们希望将通知发送给这些主题的订阅者。
以下是创建通知的触发示例:
import { Novu } from '@novu/node';
import { TriggerRecipientsTypeEnum } from '@novu/shared'
export default defineEventHandler(async (event) => {
// initiate Novu
const result = await novu.trigger('dish-based-promotional-notification',{
to: [{ type: TriggerRecipientsTypeEnum.TOPIC, topicKey }],
payload: {
promotionTitle,
promotionDetails
}
});
})
自定义通知选项
并非所有顾客都希望收到外卖服务发送的所有类型的通知。因此,我们应该允许他们选择不接收某些主题的通知。我们所做的仅仅是对特定主题的订阅者进行管理。
为了演示这一点,我们将打开 dish-based-promotional-notification 之前创建的通知模板,并在底部添加一个取消订阅链接。由于无法在模板编辑器中添加链接,我们需要将整个模板转换为自定义代码,并使用以下标记:
<div>
Hello {{subscriber.firstName}},
</div>
<div style="padding: 4px">
We have an offer you wouldn't want to miss.
</div>
<div style="padding: 4px">
{{promotionDetails}}
</div>
<div style="padding: 4px">
<a href="{{optOutLink}}?userId={{subscriber.subscriberId}}&topicKey={{topicKey}}" target="_blank">Click here</a> to unsubcribe from these emails.
</div>
我们需要订阅者的 ID 和主题键才能从主题中移除订阅者,如上面的标记所示。由于我们从未在涉及此通知的触发器中传递主题键,因此我们需要对其进行以下更改:
const result = await novu.trigger('dish-based-promotional-notification',{
to: [{ type: TriggerRecipientsTypeEnum.TOPIC, topicKey }],
payload: {
promotionTitle,
promotionDetails,
topicKey
}
});
现在,我们可以继续为用户创建订阅topic-opting-out trigger者。如前所述,我们只需从主题中移除订阅者即可。为此,我们需要按 removeSubscribers() 如下方式调用该方法。
const result = await novu.topics.removeSubscribers(topicKey, {
subscribers: [userId]
});
总结
原来这些外卖应用背后有很多运作!虽然我们还没有功能齐全的 Foody 应用,但多亏了 Novu,我们已经搭建了一个非常棒的通知系统!我们使用 Supabase 来处理用户身份验证,但最重要的部分是添加通知功能。
如果您喜欢这里的内容,请在下方评论区留言!非常荣幸能与您分享,希望您能将 Foody 推向新的高峰!
PS ConnectNovu 黑客马拉松正在进行中,欢迎大家注册,还有一些很棒的奖品,点击这里查看。
文章来源:https://dev.to/novu/creating-a-hot-new-food-delivery-app-with-novu-2e75








