Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

一个带鸟类 API 的仪表盘工具

扎卡里·萨缪尔斯

2022年3月24日

电子邮件

1 min read

一个带鸟类 API 的仪表盘工具

扎卡里·萨缪尔斯

2022年3月24日

电子邮件

1 min read

一个带鸟类 API 的仪表盘工具

这个脚本只是触及了利用 Python、Plotly Dash 和我们的 API 所能实现的可能性的表面。

将近一年前,Bird的客户成功总监Tom Mairs编写了一个邮件工具,利用Bird APIs。在这篇文章中,我从他离开的地方继续。他的工具允许定时传输任务,但如果我们想创建自己的仪表盘和事件日志呢?

也许我想为一个业务群体创建一个特定的仪表盘或一个面向客户的仪表盘,但不为用户提供对Bird UI的完全访问权限。这个脚本只是利用PythonPlotly Dash以及我们的APIs可能实现的冰山一角。构建处理高容量API数据的仪表盘时,要注意像DNS这样的基础设施组件可能成为瓶颈——我们经历过AWS DNS扩展挑战,影响了我们的数据处理能力。对于视觉工作流爱好者,你还可以探索将Flow Builder与Google Cloud Functions和Vision API整合,为你的数据处理流程添加AI驱动的自动化。

当我开始在网上搜索时,我想找到阻力最小的路径。我本可以用HTML和python自己创建所有仪表盘和UI,但在Google搜索后,我发现Plotly的Dash,它能轻松与python集成。我选择Dash的原因有两个:1) 它是开源的,2) 阅读文档后,它似乎很容易定制,适合我想做的事情。Dash是一个开源库,非常适合构建和部署具有定制用户界面的数据应用。 这使得创建UI变得极其简单。然后问题变成了,我想把这个应用程序做得多复杂?我花的时间越多,就越想添加更多功能。

对于初始项目,我想确保有一个具有可定制指标和可选择时间范围的仪表盘。最初,我从一个仪表盘开始,你只能从下拉菜单中选择一个指标。然后,随着我从同事那里得到反馈,我稍微完善了仪表盘,添加了多重选择和轴标题。我还决定为事件日志添加一个额外的标签。我达到一个令我满意的程度,为任何希望自己构建仪表盘的人提供了一个良好的起点。对于想要将实时webhook数据输入其仪表盘的开发者,请查看我们的使用Azure Functions构建webhook消费者的指南。当然,我将项目放在Github供你克隆或分叉。

入门

要访问此app,您需要确保运行 python 3.10 或更高版本,并安装以下库:

  • requests

  • dash

  • pandas

然后,将您的 API 密钥输入 App.py 并运行该应用程序。它将在http://localhost:8050上运行。有关将其部署到面向公众的服务器(例如 AWS)的更多信息,请参阅以下资源:

Creating the Dashboard Page

首先,初始化数据框架和仪表板。在未初始化仪表板的情况下,UI中不会显示仪表板。

df = pd.DataFrame({
    "Count": [0, 0],
    "Time": [0, 0]
})
fig = px.line(df, x="Time", y="Count")

然后,构建第一个选项卡。这是一个应用程序回调的组合(用于检查正在使用哪个选项卡);以及一个条件函数以检查当前选中的选项卡。下面的代码仅构建空白的仪表板和UI元素(稍后我们将处理事件选项卡)。dcc元素是Dash核心组件HTML组件,轻松允许在UI中使用HTML。

html.H2("Analytics Dashboard"),
# Multi-select dropdown
dcc.Dropdown(
    [
        "Count Accepted",
        "Count Admin Bounce",
        "Count Block Bounce",
        "Count Bounce",
        "Count Clicked",
        "Count Delayed",
        "Count Delayed First",
        "Count Delivered",
        "Count Delivered First",
        "Count Delivered Subsequent",
        "Count Generation Failed",
        "Count Generation Rejection",
        "Count Hard Bounce",
        "Count Inband Bounce",
        "Count Initial Rendered",
        "Count Injected",
        "Count Out of Band Bounce",
        "Count Policy Rejection",
        "Count Rejected",
        "Count Rendered",
        "Count Sent",
        "Count Soft Bounce",
        "Count Spam Complaint",
        "Count Targeted",
        "Count Undetermined Bounce",
        "Count Unique Clicked",
        "Count Unique Confirmed Opened",
        "Count Unique Initial Rendered",
        "Count Unique Rendered",
        "Count Unsubscribe",
        "Total Delivery Time First",
        "Total Delivery Time Subsequent",
        "Total Message Volume",
    ],
    id="y-axis",
    multi=True,
    searchable=True,
    placeholder="Select metrics(s)",
),
# Date selector (max date allowed is set to today's date)
dcc.DatePickerRange(
    id="date-picker-range",
    start_date=date(2022, 1, 1),
    end_date=date(2022, 2, 1),
    max_date_allowed=date(
        datetime.today().year,
        datetime.today().month,
        datetime.today().day,
    ),
),
# Graph object
dcc.Graph(id="Emails", figure=fig)

请注意,使用Dash如何简单地创建具有多选、可搜索下拉菜单的仪表板UI。要禁用多选或搜索,可以轻松修改创建下拉菜单的参数。我发现这个项目中最复杂的部分是从输入中构建实际的数据框架,并让HTML + CSS在UI中正常工作。

时间序列指标API允许根据日期/时间范围提取33个单独的指标。您可以通过域、活动、IP池、发送域、子账户进行深度过滤,并指定时间序列数据的精度。这些额外的过滤器以及可投送性分析可能是该项目未来的改进(需要为没有访问可投送性分析的客户实施错误捕捉)。

利用和调用指标API,我构建了一个具有用户选择参数和指定时间范围的仪表板。然后更新已初始化的仪表板。

# Build the API call utilizing the parameters provided
params = {
    "from": start_date + "T00:00",
    "to": end_date + "T00:00",
    "delimiter": ",",
    "precision": "day",
    "metrics": joined_values
}
api_url = BASE_URL + "/metrics/deliverability/time-series"
response_API = requests.get(api_url, headers={"Authorization": API_KEY}, params=params)
response_info = json.loads(response_API.text)
new_df = pd.json_normalize(response_info, record_path=['results'])
value_array = joined_values.split(",")
# Build out a new dashboard utilizing the new metrics and dates from the updated API call
fig = px.line(
    new_df,
    x=new_df['ts'],
    y=value_array,
    labels={"value": "Count", "variable": "Metric", "ts": "Date"}
)
fig.update_xaxes(title_text="Time")
fig.update_yaxes(title_text="Count")
return fig

以下是选择多个指标和扩展时间范围的示例。


Sparkpost analytics dashboard

注意:在dash图表中自动内置了许多项目(悬停、缩放、自缩放)。

首先,初始化数据框架和仪表板。在未初始化仪表板的情况下,UI中不会显示仪表板。

df = pd.DataFrame({
    "Count": [0, 0],
    "Time": [0, 0]
})
fig = px.line(df, x="Time", y="Count")

然后,构建第一个选项卡。这是一个应用程序回调的组合(用于检查正在使用哪个选项卡);以及一个条件函数以检查当前选中的选项卡。下面的代码仅构建空白的仪表板和UI元素(稍后我们将处理事件选项卡)。dcc元素是Dash核心组件HTML组件,轻松允许在UI中使用HTML。

html.H2("Analytics Dashboard"),
# Multi-select dropdown
dcc.Dropdown(
    [
        "Count Accepted",
        "Count Admin Bounce",
        "Count Block Bounce",
        "Count Bounce",
        "Count Clicked",
        "Count Delayed",
        "Count Delayed First",
        "Count Delivered",
        "Count Delivered First",
        "Count Delivered Subsequent",
        "Count Generation Failed",
        "Count Generation Rejection",
        "Count Hard Bounce",
        "Count Inband Bounce",
        "Count Initial Rendered",
        "Count Injected",
        "Count Out of Band Bounce",
        "Count Policy Rejection",
        "Count Rejected",
        "Count Rendered",
        "Count Sent",
        "Count Soft Bounce",
        "Count Spam Complaint",
        "Count Targeted",
        "Count Undetermined Bounce",
        "Count Unique Clicked",
        "Count Unique Confirmed Opened",
        "Count Unique Initial Rendered",
        "Count Unique Rendered",
        "Count Unsubscribe",
        "Total Delivery Time First",
        "Total Delivery Time Subsequent",
        "Total Message Volume",
    ],
    id="y-axis",
    multi=True,
    searchable=True,
    placeholder="Select metrics(s)",
),
# Date selector (max date allowed is set to today's date)
dcc.DatePickerRange(
    id="date-picker-range",
    start_date=date(2022, 1, 1),
    end_date=date(2022, 2, 1),
    max_date_allowed=date(
        datetime.today().year,
        datetime.today().month,
        datetime.today().day,
    ),
),
# Graph object
dcc.Graph(id="Emails", figure=fig)

请注意,使用Dash如何简单地创建具有多选、可搜索下拉菜单的仪表板UI。要禁用多选或搜索,可以轻松修改创建下拉菜单的参数。我发现这个项目中最复杂的部分是从输入中构建实际的数据框架,并让HTML + CSS在UI中正常工作。

时间序列指标API允许根据日期/时间范围提取33个单独的指标。您可以通过域、活动、IP池、发送域、子账户进行深度过滤,并指定时间序列数据的精度。这些额外的过滤器以及可投送性分析可能是该项目未来的改进(需要为没有访问可投送性分析的客户实施错误捕捉)。

利用和调用指标API,我构建了一个具有用户选择参数和指定时间范围的仪表板。然后更新已初始化的仪表板。

# Build the API call utilizing the parameters provided
params = {
    "from": start_date + "T00:00",
    "to": end_date + "T00:00",
    "delimiter": ",",
    "precision": "day",
    "metrics": joined_values
}
api_url = BASE_URL + "/metrics/deliverability/time-series"
response_API = requests.get(api_url, headers={"Authorization": API_KEY}, params=params)
response_info = json.loads(response_API.text)
new_df = pd.json_normalize(response_info, record_path=['results'])
value_array = joined_values.split(",")
# Build out a new dashboard utilizing the new metrics and dates from the updated API call
fig = px.line(
    new_df,
    x=new_df['ts'],
    y=value_array,
    labels={"value": "Count", "variable": "Metric", "ts": "Date"}
)
fig.update_xaxes(title_text="Time")
fig.update_yaxes(title_text="Count")
return fig

以下是选择多个指标和扩展时间范围的示例。


Sparkpost analytics dashboard

注意:在dash图表中自动内置了许多项目(悬停、缩放、自缩放)。

首先,初始化数据框架和仪表板。在未初始化仪表板的情况下,UI中不会显示仪表板。

df = pd.DataFrame({
    "Count": [0, 0],
    "Time": [0, 0]
})
fig = px.line(df, x="Time", y="Count")

然后,构建第一个选项卡。这是一个应用程序回调的组合(用于检查正在使用哪个选项卡);以及一个条件函数以检查当前选中的选项卡。下面的代码仅构建空白的仪表板和UI元素(稍后我们将处理事件选项卡)。dcc元素是Dash核心组件HTML组件,轻松允许在UI中使用HTML。

html.H2("Analytics Dashboard"),
# Multi-select dropdown
dcc.Dropdown(
    [
        "Count Accepted",
        "Count Admin Bounce",
        "Count Block Bounce",
        "Count Bounce",
        "Count Clicked",
        "Count Delayed",
        "Count Delayed First",
        "Count Delivered",
        "Count Delivered First",
        "Count Delivered Subsequent",
        "Count Generation Failed",
        "Count Generation Rejection",
        "Count Hard Bounce",
        "Count Inband Bounce",
        "Count Initial Rendered",
        "Count Injected",
        "Count Out of Band Bounce",
        "Count Policy Rejection",
        "Count Rejected",
        "Count Rendered",
        "Count Sent",
        "Count Soft Bounce",
        "Count Spam Complaint",
        "Count Targeted",
        "Count Undetermined Bounce",
        "Count Unique Clicked",
        "Count Unique Confirmed Opened",
        "Count Unique Initial Rendered",
        "Count Unique Rendered",
        "Count Unsubscribe",
        "Total Delivery Time First",
        "Total Delivery Time Subsequent",
        "Total Message Volume",
    ],
    id="y-axis",
    multi=True,
    searchable=True,
    placeholder="Select metrics(s)",
),
# Date selector (max date allowed is set to today's date)
dcc.DatePickerRange(
    id="date-picker-range",
    start_date=date(2022, 1, 1),
    end_date=date(2022, 2, 1),
    max_date_allowed=date(
        datetime.today().year,
        datetime.today().month,
        datetime.today().day,
    ),
),
# Graph object
dcc.Graph(id="Emails", figure=fig)

请注意,使用Dash如何简单地创建具有多选、可搜索下拉菜单的仪表板UI。要禁用多选或搜索,可以轻松修改创建下拉菜单的参数。我发现这个项目中最复杂的部分是从输入中构建实际的数据框架,并让HTML + CSS在UI中正常工作。

时间序列指标API允许根据日期/时间范围提取33个单独的指标。您可以通过域、活动、IP池、发送域、子账户进行深度过滤,并指定时间序列数据的精度。这些额外的过滤器以及可投送性分析可能是该项目未来的改进(需要为没有访问可投送性分析的客户实施错误捕捉)。

利用和调用指标API,我构建了一个具有用户选择参数和指定时间范围的仪表板。然后更新已初始化的仪表板。

# Build the API call utilizing the parameters provided
params = {
    "from": start_date + "T00:00",
    "to": end_date + "T00:00",
    "delimiter": ",",
    "precision": "day",
    "metrics": joined_values
}
api_url = BASE_URL + "/metrics/deliverability/time-series"
response_API = requests.get(api_url, headers={"Authorization": API_KEY}, params=params)
response_info = json.loads(response_API.text)
new_df = pd.json_normalize(response_info, record_path=['results'])
value_array = joined_values.split(",")
# Build out a new dashboard utilizing the new metrics and dates from the updated API call
fig = px.line(
    new_df,
    x=new_df['ts'],
    y=value_array,
    labels={"value": "Count", "variable": "Metric", "ts": "Date"}
)
fig.update_xaxes(title_text="Time")
fig.update_yaxes(title_text="Count")
return fig

以下是选择多个指标和扩展时间范围的示例。


Sparkpost analytics dashboard

注意:在dash图表中自动内置了许多项目(悬停、缩放、自缩放)。

创建Event Details 页面

活动详情页面稍显复杂,因为我不知道如何以一种易于阅读的方式呈现所有活动指标。我考虑过在此页面添加过滤参数,但我认为这样做会为此项目增加大量时间,因为那样表格必须是动态的(同时添加参数、回调等)。我决定显示所有活动并将时间戳放在最前面(因为如果不这样做,图表将不易阅读)。起初,我发现仅使用原始HTML,表格对眼睛来说非常困难。没有边框,也没有标题与行的颜色差异。为了使表格更易于阅读,我能够在Dash中使用CSS。

活动详情的想法几乎和仪表板相同,除了这次我调用事件API并导入所有事件。请注意,活动详情仅显示最近的10个事件(利用max_rows参数和API过滤)。这可以增加,但是我决定只显示最近的10个事件,因为显示的活动越多,API调用的时间就越长。可以进行的一项重大改进是能够在UI中分页并包含“下一页/上一页”。

要构建事件选项卡(页面),首先,我调用事件API并将JSON响应解析为数据框。然后我对数据框进行排序和重新排序,以将时间戳放在第一列。最后,通过遍历数据框构建HTML表格。

# Build out and call the events API
params = {
    "events": "delivery,injection,bounce,delay,policy_rejection,out_of_band,open,click,"
              "generation_failure,generation_rejection,spam_complaint,list_unsubscribe,link_unsubscribe",
    "delimiter": ",",
    "page": "1",
    "per_page": "10",
}
api_url = f"{BASE_URL}/events/message"
response_API = requests.get(api_url, headers={"Authorization": API_KEY}, params=params)
response_info = response_API.json()
new_df = pd.json_normalize(response_info, record_path=["results"])
max_rows = 10  # Max number of results to show in the events table
# Sort columns and place timestamp as the first column in the table
new_df = new_df.reindex(sorted(new_df.columns), axis=1)
cols = ["timestamp"]
new_df = new_df[cols + [c for c in new_df.columns if c not in cols]]
# Show the new HTML with the events table (note: this table also references table.css)
return html.Div([
    html.H2("Event Details"),
    html.Table([
        html.Thead(
            html.Tr([html.Th(col) for col in new_df.columns], className="table_css")
        ),
        html.Tbody([
            html.Tr([
                html.Td(new_df.iloc[i][col], className="table_css")
                for col in new_df.columns
            ])
            for i in range(min(len(new_df), max_rows))
        ])
    ])
])

这在UI中看起来像这样。

Sparkpost event details

下一步

对于想要创建自己仪表盘或事件日志的人来说,这是一个不错的开始。由于这里的可定制性,天空是无限的。

如上所述,可以进行的一些未来改进包括:

  • 添加交付分析功能到仪表板

  • 为仪表板添加更多过滤器

  • 可能的缓存选择,以便不必每次都调用API来显示页面

  • UI 改进

  • 为事件详情页面添加过滤和分页功能

我很感兴趣听取任何反馈或关于扩展此项目的建议。

~ Zach Samuels, Bird高级解决方案工程师

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

R

Reach

G

Grow

M

Manage

A

Automate

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。