Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

Una herramienta de paneles de control con APIs de pájaros

Zacarías Samuels

24 mar 2022

Correo electrónico

1 min read

Una herramienta de paneles de control con APIs de pájaros

Zacarías Samuels

24 mar 2022

Correo electrónico

1 min read

Una herramienta de paneles de control con APIs de pájaros

Este script solo roza la superficie de lo que es posible utilizando Python, Plotly Dash y nuestras API.

Hace casi un año, Tom Mairs, director de éxito del cliente de Bird, escribió una herramienta de correo utilizando Bird APIs. En este artículo, continúo desde donde él lo dejó. Su herramienta permite la transmisión programada de trabajos, pero ¿qué pasa si queremos crear nuestros propios paneles y registros de eventos?

Tal vez quiera crear un panel específico para un grupo empresarial o un tablero orientado al cliente, pero no proporcionar a los usuarios acceso completo a la IU de Bird. Este script solo roza la superficie de lo que es posible utilizando Python, Plotly Dash y nuestras APIs. Al construir paneles que procesan datos de API de alto volumen, ten en cuenta que los componentes de infraestructura como DNS pueden convertirse en cuellos de botella: hemos experimentado desafíos de escalado de DNS de AWS que afectaron nuestras capacidades de procesamiento de datos. Para los entusiastas del flujo de trabajo visual, también puedes explorar la integración de Flow Builder con Google Cloud Functions y Vision API para añadir automatización impulsada por IA a tus flujos de trabajo de procesamiento de datos.

Cuando comencé mi búsqueda en línea, quise encontrar el camino de menor resistencia. Podría haber creado todos los paneles e IU yo mismo en HTML y python, sin embargo, después de algunas búsquedas en Google, me encontré con Plotly’s Dash, que se integra fácilmente con python. Elegí Dash por 2 razones: 1) es de código abierto, y 2) después de leer la documentación, parecía fácilmente personalizable para lo que estaba intentando hacer. Dash es una biblioteca de código abierto que es ideal para construir y desplegar aplicaciones de datos con interfaces de usuario personalizadas. Esto hizo que crear una IU fuera extremadamente simple. La pregunta entonces era, ¿cuán complejo quería hacer este app? Cuanto más tiempo pasé, más características quería añadir.

Para el proyecto inicial, quise asegurarme de que tenía un panel con métricas personalizables y un marco de tiempo seleccionable. Inicialmente, comencé con un panel donde solo podías elegir una métrica del menú desplegable. Luego, a medida que recibí comentarios de los colegas, refiné un poco el panel para añadir selección múltiple y títulos de ejes. También decidí añadir una pestaña adicional para un registro de eventos. Llegué al punto en el que estaba satisfecho con lo que tenía como un buen punto de partida para cualquiera que deseara construir sus propios paneles. Para los desarrolladores que quieran alimentar sus paneles con datos de webhook en tiempo real, consulta nuestra guía sobre construcción de consumidores de webhook con Azure Functions. Por supuesto, puse el proyecto en Github para que lo clonen o ramifiquen.

Empezando

Para acceder a esta app, necesitará asegurarse de que está ejecutando python 3.10 o superior e instalar las siguientes bibliotecas:

  • requests

  • dash

  • pandas

Luego, introduzca su clave API en App.py y ejecute la app. Se ejecutará en http://localhost:8050. Para obtener más información sobre cómo implementarlo en un servidor público (como AWS), consulte los siguientes recursos:

Creando la Página del Dashboard

Primero, inicialice el marco de datos y el tablero. Sin inicializar el tablero, no aparecerá ningún tablero en la interfaz de usuario (UI).

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

Luego, construya la primera pestaña. Esta es una combinación de una devolución de llamada de la aplicación (para verificar qué pestaña se está utilizando) junto con una función condicional para verificar qué pestaña está actualmente seleccionada. El código a continuación construye solo el tablero en blanco y los elementos de la UI (llegaremos a la pestaña de eventos más adelante). Los elementos dcc son los Dash Core Components y los HTML Components permiten fácilmente que el HTML se use en la UI.

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)

Note con dash lo sencillo que es crear una interfaz de usuario (UI) de tablero con un menú desplegable de selección múltiple y búsqueda. Para desactivar la selección múltiple o la búsqueda, los parámetros para crear un menú desplegable se pueden modificar fácilmente. Encontré que la parte más compleja de este proyecto fue construir realmente el marco de datos a partir de las entradas, así como lograr que el HTML + CSS funcionara correctamente en la UI.

El Time Series Metrics API permite extraer 33 métricas individuales basadas en un rango de fecha/hora. Puedes filtrar más profundamente por Dominios, Campañas, IP Pools, Dominios de Envío, Subcuentas y especificar la Precisión de los datos de series temporales. Estos filtros adicionales junto con los análisis de entregabilidad podrían ser una mejora futura para este proyecto (se necesitaría implementar captura de errores para clientes que no tengan acceso a análisis de entregabilidad).

Utilizando y llamando al Metrics API, construyo un tablero con los parámetros seleccionados por el usuario y el intervalo de tiempo especificado. El tablero inicializado se actualiza luego.

# 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

El siguiente es un ejemplo de métricas múltiples seleccionadas y un intervalo de tiempo expandido.


Sparkpost analytics dashboard

Nota: hay muchos elementos incorporados automáticamente en el gráfico dash (flotar, zoom, escala automática).

Primero, inicialice el marco de datos y el tablero. Sin inicializar el tablero, no aparecerá ningún tablero en la interfaz de usuario (UI).

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

Luego, construya la primera pestaña. Esta es una combinación de una devolución de llamada de la aplicación (para verificar qué pestaña se está utilizando) junto con una función condicional para verificar qué pestaña está actualmente seleccionada. El código a continuación construye solo el tablero en blanco y los elementos de la UI (llegaremos a la pestaña de eventos más adelante). Los elementos dcc son los Dash Core Components y los HTML Components permiten fácilmente que el HTML se use en la UI.

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)

Note con dash lo sencillo que es crear una interfaz de usuario (UI) de tablero con un menú desplegable de selección múltiple y búsqueda. Para desactivar la selección múltiple o la búsqueda, los parámetros para crear un menú desplegable se pueden modificar fácilmente. Encontré que la parte más compleja de este proyecto fue construir realmente el marco de datos a partir de las entradas, así como lograr que el HTML + CSS funcionara correctamente en la UI.

El Time Series Metrics API permite extraer 33 métricas individuales basadas en un rango de fecha/hora. Puedes filtrar más profundamente por Dominios, Campañas, IP Pools, Dominios de Envío, Subcuentas y especificar la Precisión de los datos de series temporales. Estos filtros adicionales junto con los análisis de entregabilidad podrían ser una mejora futura para este proyecto (se necesitaría implementar captura de errores para clientes que no tengan acceso a análisis de entregabilidad).

Utilizando y llamando al Metrics API, construyo un tablero con los parámetros seleccionados por el usuario y el intervalo de tiempo especificado. El tablero inicializado se actualiza luego.

# 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

El siguiente es un ejemplo de métricas múltiples seleccionadas y un intervalo de tiempo expandido.


Sparkpost analytics dashboard

Nota: hay muchos elementos incorporados automáticamente en el gráfico dash (flotar, zoom, escala automática).

Primero, inicialice el marco de datos y el tablero. Sin inicializar el tablero, no aparecerá ningún tablero en la interfaz de usuario (UI).

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

Luego, construya la primera pestaña. Esta es una combinación de una devolución de llamada de la aplicación (para verificar qué pestaña se está utilizando) junto con una función condicional para verificar qué pestaña está actualmente seleccionada. El código a continuación construye solo el tablero en blanco y los elementos de la UI (llegaremos a la pestaña de eventos más adelante). Los elementos dcc son los Dash Core Components y los HTML Components permiten fácilmente que el HTML se use en la UI.

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)

Note con dash lo sencillo que es crear una interfaz de usuario (UI) de tablero con un menú desplegable de selección múltiple y búsqueda. Para desactivar la selección múltiple o la búsqueda, los parámetros para crear un menú desplegable se pueden modificar fácilmente. Encontré que la parte más compleja de este proyecto fue construir realmente el marco de datos a partir de las entradas, así como lograr que el HTML + CSS funcionara correctamente en la UI.

El Time Series Metrics API permite extraer 33 métricas individuales basadas en un rango de fecha/hora. Puedes filtrar más profundamente por Dominios, Campañas, IP Pools, Dominios de Envío, Subcuentas y especificar la Precisión de los datos de series temporales. Estos filtros adicionales junto con los análisis de entregabilidad podrían ser una mejora futura para este proyecto (se necesitaría implementar captura de errores para clientes que no tengan acceso a análisis de entregabilidad).

Utilizando y llamando al Metrics API, construyo un tablero con los parámetros seleccionados por el usuario y el intervalo de tiempo especificado. El tablero inicializado se actualiza luego.

# 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

El siguiente es un ejemplo de métricas múltiples seleccionadas y un intervalo de tiempo expandido.


Sparkpost analytics dashboard

Nota: hay muchos elementos incorporados automáticamente en el gráfico dash (flotar, zoom, escala automática).

Creando la Event Details Page

La página de detalles del evento fue un poco más difícil porque no sabía la mejor manera de presentar todos los métricas del evento de una manera fácil de leer. Consideré agregar parámetros de filtrado a esta página, sin embargo, decidí que eso añadiría una cantidad significativa de tiempo a este proyecto ya que la tabla tendría que ser dinámica (junto con agregar los parámetros, callbacks, etc.). Me decidí por mostrar todos los eventos y colocar la marca de tiempo primero (ya que sin poner la marca de tiempo primero, la tabla no era fácil de leer). Inicialmente, encontré que con solo el HTML en bruto, la tabla era increíblemente difícil para la vista. No había bordes ni diferencias de color entre el encabezado y las filas. Para hacer la tabla más fácil de leer, pude usar CSS dentro de Dash.

La idea para los detalles del evento es casi la misma que el dashboard, excepto que esta vez, llamo al Events API y traigo todos los eventos. Observe que los detalles del evento solo muestran los 10 eventos más recientes (utilizando el parámetro max_rows y el filtrado de la API). Esto se puede aumentar, sin embargo, me decidí por mostrar los 10 eventos más recientes porque cuantos más eventos se muestran, más tiempo tarda la llamada a la API. Una mejora significativa que se podría hacer sería la capacidad de paginar e incluir una Página Siguiente / Página Anterior en la interfaz de usuario.

Para construir la pestaña (página) de eventos, primero, llamo al Events API y analizo la respuesta JSON en un marco de datos. Luego, ordeno y reorganizo el marco de datos para poner la marca de tiempo como la primera columna. Finalmente, construyo la tabla HTML iterando a través del marco de datos.

# 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))
        ])
    ])
])

Lo cual se ve así en la interfaz de usuario.

Sparkpost event details

Siguientes pasos

Para alguien que busca crear su propio tablero o registro de eventos, esto es un buen comienzo. Con la personalización aquí, el cielo es el límite.

Como se discutió anteriormente, algunas mejoras futuras que podrían hacerse son:

  • Agregar análisis de entregabilidad al tablero

  • Agregar más filtros al tablero

  • Posibles opciones de almacenamiento en caché para que la API no se llame cada vez para mostrar las páginas

  • Mejoras en la UI

  • Agregar filtrado y paginación a la página de detalles del evento

Me interesaría escuchar comentarios o sugerencias para expandir este proyecto.

~ Zach Samuels, Bird Senior Solutions Engineer

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

R

Reach

G

Grow

M

Manage

A

Automate

Company

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.