Il y a presque un an, Tom Mairs, directeur de la réussite client chez Bird, a écrit un outil de mailer utilisant les API de Bird. Dans cet article, je reprends là où il s'est arrêté. Son outil permet la transmission chronométrée de tâches, mais que faire si nous voulons créer nos propres tableaux de bord et journaux d'événements ?
Peut-être que je veux créer un tableau de bord spécifique pour un groupe d'affaires ou un tableau de bord destiné aux clients, mais sans donner aux utilisateurs un accès complet à l'UI de Bird. Ce script effleure juste la surface de ce qui est possible en utilisant Python, Plotly Dash, et nos API.
Alors que je commençais ma recherche en ligne, je voulais trouver le chemin de la moindre résistance. J'aurais pu créer tous les tableaux de bord et l'UI moi-même en HTML et python, cependant, après quelques recherches sur Google, j'ai découvert Dash de Plotly, qui s'intègre facilement avec python. J'ai choisi Dash pour 2 raisons : 1) c'est open source, et 2) après avoir lu la documentation, il semblait facilement personnalisable pour ce que j'essayais de faire. Dash est une bibliothèque open-source qui est idéale pour construire et déployer des applications de données avec des interfaces utilisateur personnalisées. Cela a rendu la création d'une UI extrêmement simple. La question est donc devenue, à quel point voulais-je rendre cette application complexe ? Plus je passais de temps, plus j'avais envie d'ajouter des fonctionnalités.
Pour le projet initial, je voulais m'assurer que j'avais un tableau de bord avec des métriques personnalisables et une plage de temps sélectionnable. Au départ, j'ai commencé avec un tableau de bord où vous ne pouviez sélectionner qu'une seule métrique dans le menu déroulant. Puis, au fur et à mesure que j'ai reçu des retours de collègues, j'ai affiné un peu le tableau de bord pour ajouter une sélection multiple et des titres d'axes. J'ai aussi décidé d'ajouter un onglet supplémentaire pour un journal des événements. Je suis arrivé à un point où j'étais satisfait de ce que j'avais comme bon point de départ pour quiconque souhaitant créer ses propres tableaux de bord. Bien sûr, j'ai mis le projet sur Github pour que vous puissiez le cloner ou le bifurquer.
Guide de démarrage
Pour accéder à cette application, vous devrez vous assurer que vous exécutez python 3.10 ou une version ultérieure et installer les bibliothèques suivantes :
requests
dash
pandas
Ensuite, entrez votre clé API dans App.py et exécutez l'application. Elle s'exécutera sur http://localhost:8050. Pour plus d'informations sur le déploiement de cela sur un serveur accessible au public (comme AWS), consultez les ressources suivantes :
Création de la page du tableau de bord
Tout d'abord, initialisez le cadre de données et le tableau de bord. Sans initialiser le tableau de bord, aucun tableau de bord n'apparaîtra dans l'UI.
df = pd.DataFrame({
"Count": [0,0],
"Time": [0,0]
})
fig = px.line(df,x="Time",y="Count")
Ensuite, créez le premier onglet. C'est une combinaison d'un rappel d'application (pour vérifier quel onglet est utilisé) ; avec une fonction conditionnelle pour vérifier quel onglet est actuellement sélectionné. Le code ci-dessous crée uniquement le tableau de bord vide et les éléments de l'UI (nous aborderons plus tard l'onglet des événements). Les éléments dcc sont les Composants de base de Dash et les Composants HTML permettent facilement d'utiliser du HTML dans l'UI.
html.H2('Tableau de bord d'analytique'),
#Menu déroulant à sélection multiple
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="Sélectionnez la(les) métrique(s)"),
#Sélecteur de dates (la date max autorisée est réglée à la date du jour) 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), ),
#Objet graphique dcc.Graph( id='Emails', figure=fig )
Notez avec Dash à quel point il est simple de créer une UI de tableau de bord avec un menu déroulant à sélection multiple et recherchable. Pour désactiver la sélection multiple ou la recherche, les paramètres pour créer un menu déroulant peuvent être facilement modifiés. J'ai trouvé que la partie la plus complexe de ce projet était de construire le cadre de données réel à partir des entrées, ainsi que de faire fonctionner correctement le HTML + CSS dans l'UI.
L'API des indicateurs de séries temporelles permet de récupérer 33 indicateurs individuels en fonction d'une plage de date/heure. Vous pouvez filtrer plus en profondeur par domaines, campagnes, pools d'IP, domaines d'envoi, sous-comptes, et préciser la précision des données de séries temporelles. Ces filtres supplémentaires, associés aux analyses de délivrabilité, pourraient constituer une amélioration future de ce projet (la capture d'erreurs devrait être mise en œuvre pour les clients qui n'ont pas accès aux analyses de délivrabilité).
En utilisant et appelant l'API des indicateurs, je construis un tableau de bord avec les paramètres sélectionnés par l'utilisateur et la plage de temps spécifiée. Le tableau de bord initial est ensuite mis à jour.
#Construire l'appel API en utilisant les paramètres fournis 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(",") #Construire un nouveau tableau de bord en utilisant les nouvelles métriques et dates de l'appel API mis à jour fig = px.line(new_df, x=new_df['ts'], y=value_array, labels={"value": "Count", "variable": "Metric","ts":"Date"}) fig.update_xaxes(title_text="Temps") fig.update_yaxes(title_text="Count") return fig
Voici un exemple de plusieurs métriques sélectionnées et d'une plage de temps étendue.
Note : il y a de nombreux éléments automatiquement intégrés dans le graphique Dash (surligner, zoom, échelle automatique).
Création de la page des détails des événements
La page des détails des événements était un peu plus difficile car je ne savais pas la meilleure façon de présenter toutes les métriques des événements d'une manière facile à lire. J'ai envisagé d'ajouter des paramètres de filtrage à cette page, cependant, j'ai décidé que cela ajouterait une quantité significative de temps à ce projet car le tableau devrait alors être dynamique (en plus d'ajouter les paramètres, les rappels, etc.). J'ai opté pour montrer tous les événements et placer le timestamp en premier (car sans mettre le timestamp en premier, le graphique n'était pas facile à lire). Au départ, j'ai constaté qu'avec juste le HTML brut, le tableau était incroyablement difficile à lire. Il n'y avait pas de bordures et aucune différence de couleur pour l'en-tête par rapport aux lignes. Pour rendre le tableau plus facile à lire, j'ai pu utiliser le CSS dans Dash.
L'idée pour les détails des événements est presque la même que celle du tableau de bord, sauf cette fois, j'appelle l'API des événements et j'importe tous les événements. Notez que les détails des événements n'affichent que les 10 événements les plus récents (en utilisant le paramètre max_rows et le filtrage API). Cela peut être augmenté, cependant, j'ai décidé de montrer les 10 événements les plus récents car plus d'événements sont affichés, plus l'appel API prend de temps. Une amélioration significative qui pourrait être apportée serait la possibilité de paginer et d'inclure une page suivante / précédente dans l'UI.
Pour construire l'onglet des événements (page), tout d'abord, j'appelle l'API des événements et parse la réponse JSON dans un cadre de données. Ensuite, je trie et réorganise le cadre de données pour mettre le timestamp comme première colonne. Enfin, je construis le tableau HTML en itérant à travers le cadre de données.
#Construire et appeler l'API des événements 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 #Nombre maximum de résultats à afficher dans le tableau des événements #Placer le timestamp comme première colonne dans le tableau 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]] #Afficher le nouveau HTML avec le tableau des événements (notez que ce tableau référence également table.css) return html.Div([ html.H2("Détails des événements"), 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)) ]) ]) ])
Ce qui ressemble à ceci dans l'UI.
Prochaines étapes
Pour quelqu'un cherchant à créer son propre tableau de bord ou journal d'événements, c'est un bon départ. Avec le niveau de personnalisation ici, le ciel est la limite.
Comme discuté ci-dessus, certaines améliorations futures qui pourraient être apportées sont :
Ajouter des analyses de délivrabilité au tableau de bord
Ajouter plus de filtres au tableau de bord
Options éventuelles de mise en cache pour que l'API ne soit pas appelée à chaque fois pour afficher les pages
Améliorations de l'UI
Ajouter un filtrage et une pagination à la page des détails des événements
Je serais intéressé d'entendre des retours ou des suggestions pour élargir ce projet.
~ Zach Samuels, Ingénieur Senior en Solutions chez Bird