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, el director de éxito del cliente de Bird, escribió una herramienta de correo utilizando Bird APIs. En este artículo, retomo donde él lo dejó. Su herramienta permite la transmisión programada de trabajos, pero ¿qué pasa si queremos crear nuestros propios paneles de control y registros de eventos?

Tal vez quiera crear un panel de control específico para un grupo empresarial o uno dirigido a clientes, pero sin proporcionar a los usuarios acceso completo a la interfaz de Bird. Este script solo toca la superficie de lo que es posible utilizando Python, Plotly Dash y nuestros APIs. Al construir paneles que procesan datos de API de alto volumen, tenga en cuenta que los componentes de infraestructura como el DNS pueden convertirse en cuellos de botella; hemos experimentado desafíos de escalado de AWS DNS que afectaron nuestras capacidades de procesamiento de datos. Para los entusiastas del flujo de trabajo visual, también pueden explorar integrar Flow Builder con Google Cloud Functions y Vision API para agregar automatización potenciada por IA a sus flujos de procesamiento de datos.

Cuando comencé mi búsqueda en línea, quería encontrar el camino de menor resistencia. Podría haber creado todos los paneles de control y la interfaz de usuario por mí 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 quería 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 interfaz de usuario fuera extremadamente simple. La pregunta entonces se convirtió en, ¿cuán complejo quería hacer esta aplicación? Cuanto más tiempo dedicaba, más características quería agregar.

Para el proyecto inicial, quería asegurarme de tener un panel de control con métricas personalizables y un marco de tiempo seleccionable. Inicialmente, comencé con un panel de control donde solo podías elegir una métrica del menú desplegable. Luego, a medida que recibía comentarios de colegas, refiné un poco el panel de control para agregar multiselección y títulos de ejes. También decidí agregar una pestaña adicional para un registro de eventos. Llegué al punto en que me satisfacía con lo que tenía como un buen punto de partida para cualquiera que desee desarrollar sus propios paneles de control. Para los desarrolladores que quieren alimentar datos de webhook en tiempo real en sus paneles, echa un vistazo a nuestra guía sobre cómo construir consumidores de webhook con Azure Functions. Por supuesto, puse el proyecto en Github para que puedas clonarlo o crear tu propia rama.

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 implementar esto en un servidor público (como AWS), consulte los siguientes recursos:

Creando la Página del Dashboard

Primero, inicializa el marco de datos y el panel de control. Sin inicializar el panel de control, no aparecerá en la IU.

df = pd.DataFrame({

"Count": [0,0],

"Time": [0,0]

})

fig = px.line(df,x="Time",y="Count")

Luego, construye la primera pestaña. Esto es una combinación de un callback de la aplicación (para verificar qué pestaña se está utilizando); junto con una función condicional para verificar qué pestaña está seleccionada actualmente. El siguiente código sólo construye el panel de control en blanco y los elementos de la IU (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 el uso de HTML en la IU.

html.H2('Analytics Dashboard'),

#Selección múltiple en el menú desplegable

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)"),

#Selector de fecha (la fecha máxima permitida se establece en la fecha de hoy) 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), ),

#Objeto de gráfico dcc.Graph( id='Emails', figure=fig )

Nota lo sencillo que es crear una IU de panel de control con dash que tenga 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 efectivamente el marco de datos desde las entradas, así como lograr que el HTML + CSS funcionaran correctamente en la IU.

La Time Series Metrics API permite obtener 33 métricas individuales basadas en un rango de fecha/tiempo. Puedes filtrar más a fondo por Dominios, Campañas, Pools de IP, 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 entrega podrían ser una mejora futura para este proyecto (se necesitaría implementar la captura de errores para los clientes que no tienen acceso a los análisis de entrega).

Utilizando y llamando a la Metrics API, construyo un panel de control con los parámetros seleccionados por el usuario y el marco de tiempo especificado. A continuación, se actualiza el panel de control inicializado.

#Construir la llamada a la API utilizando los parámetros proporcionados 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(",") #Construir un nuevo panel de control utilizando las nuevas métricas y fechas de la llamada a la API actualizada 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últiples métricas seleccionadas y un marco de tiempo expandido.


Nota: hay muchos elementos incorporados automáticamente en el gráfico de dash (hover, zoom, autoscala).

Primero, inicializa el marco de datos y el panel de control. Sin inicializar el panel de control, no aparecerá en la IU.

df = pd.DataFrame({

"Count": [0,0],

"Time": [0,0]

})

fig = px.line(df,x="Time",y="Count")

Luego, construye la primera pestaña. Esto es una combinación de un callback de la aplicación (para verificar qué pestaña se está utilizando); junto con una función condicional para verificar qué pestaña está seleccionada actualmente. El siguiente código sólo construye el panel de control en blanco y los elementos de la IU (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 el uso de HTML en la IU.

html.H2('Analytics Dashboard'),

#Selección múltiple en el menú desplegable

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)"),

#Selector de fecha (la fecha máxima permitida se establece en la fecha de hoy) 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), ),

#Objeto de gráfico dcc.Graph( id='Emails', figure=fig )

Nota lo sencillo que es crear una IU de panel de control con dash que tenga 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 efectivamente el marco de datos desde las entradas, así como lograr que el HTML + CSS funcionaran correctamente en la IU.

La Time Series Metrics API permite obtener 33 métricas individuales basadas en un rango de fecha/tiempo. Puedes filtrar más a fondo por Dominios, Campañas, Pools de IP, 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 entrega podrían ser una mejora futura para este proyecto (se necesitaría implementar la captura de errores para los clientes que no tienen acceso a los análisis de entrega).

Utilizando y llamando a la Metrics API, construyo un panel de control con los parámetros seleccionados por el usuario y el marco de tiempo especificado. A continuación, se actualiza el panel de control inicializado.

#Construir la llamada a la API utilizando los parámetros proporcionados 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(",") #Construir un nuevo panel de control utilizando las nuevas métricas y fechas de la llamada a la API actualizada 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últiples métricas seleccionadas y un marco de tiempo expandido.


Nota: hay muchos elementos incorporados automáticamente en el gráfico de dash (hover, zoom, autoscala).

Primero, inicializa el marco de datos y el panel de control. Sin inicializar el panel de control, no aparecerá en la IU.

df = pd.DataFrame({

"Count": [0,0],

"Time": [0,0]

})

fig = px.line(df,x="Time",y="Count")

Luego, construye la primera pestaña. Esto es una combinación de un callback de la aplicación (para verificar qué pestaña se está utilizando); junto con una función condicional para verificar qué pestaña está seleccionada actualmente. El siguiente código sólo construye el panel de control en blanco y los elementos de la IU (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 el uso de HTML en la IU.

html.H2('Analytics Dashboard'),

#Selección múltiple en el menú desplegable

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)"),

#Selector de fecha (la fecha máxima permitida se establece en la fecha de hoy) 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), ),

#Objeto de gráfico dcc.Graph( id='Emails', figure=fig )

Nota lo sencillo que es crear una IU de panel de control con dash que tenga 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 efectivamente el marco de datos desde las entradas, así como lograr que el HTML + CSS funcionaran correctamente en la IU.

La Time Series Metrics API permite obtener 33 métricas individuales basadas en un rango de fecha/tiempo. Puedes filtrar más a fondo por Dominios, Campañas, Pools de IP, 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 entrega podrían ser una mejora futura para este proyecto (se necesitaría implementar la captura de errores para los clientes que no tienen acceso a los análisis de entrega).

Utilizando y llamando a la Metrics API, construyo un panel de control con los parámetros seleccionados por el usuario y el marco de tiempo especificado. A continuación, se actualiza el panel de control inicializado.

#Construir la llamada a la API utilizando los parámetros proporcionados 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(",") #Construir un nuevo panel de control utilizando las nuevas métricas y fechas de la llamada a la API actualizada 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últiples métricas seleccionadas y un marco de tiempo expandido.


Nota: hay muchos elementos incorporados automáticamente en el gráfico de dash (hover, zoom, autoscala).

Creando la Event Details Page

La página de detalles del evento era un poco más difícil porque no sabía la mejor manera de presentar todas las métricas de los eventos 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, devoluciones de llamada, etc.). Me decidí por mostrar todos los eventos y colocar la marca de tiempo primero (ya que sin poner la marca de tiempo primero, el gráfico no era fácil de leer). Inicialmente, descubrí que con solo el HTML sin procesar, la tabla era increíblemente difícil de leer. No había bordes ni diferencias de color entre el encabezado y las filas. Para hacer que la tabla fuera 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 panel de control, excepto que esta vez, llamo al Events API y traigo todos los eventos. Note que los detalles del evento solo muestran los 10 eventos más recientes (utilizando el parámetro max_rows y el filtrado de API). Esto puede aumentarse, sin embargo, decidí mostrar los 10 eventos más recientes porque mientras más eventos se muestren, más tiempo toma la llamada de 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 de eventos (página), primero, llamo al Events API y analizo la respuesta JSON en un marco de datos. Luego ordeno y reordeno 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.

#Construir y llamar a los parámetros del 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 = BASE_URL + "/events/message" 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']) max_rows=10 #Número máximo de resultados mostrados en la tabla de eventos #Colocar la marca de tiempo como la primera columna en la tabla 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]] #Mostrar el nuevo HTML con la tabla de eventos (note, esta tabla también hace referencia a 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)) ]) ]) ])

Que se ve así en la interfaz de usuario.

Siguientes pasos

Para alguien que busca crear su propio panel o registro de eventos, este 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 analíticas de entregabilidad al panel

  • Agregar más filtros al panel

  • Opciones de almacenamiento en caché posibles para que el API no se llame cada vez para mostrar las páginas

  • Mejoras de UI

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

Me interesaría escuchar cualquier comentario 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.