Bijna een jaar geleden schreef Tom Mairs, de directeur klantensuccess van Bird, een mailtool die gebruikmaakt van de Bird API's. In deze post pak ik het op waar hij was gebleven. Zijn tool maakt tijdgebonden verzending van taken mogelijk, maar wat als we onze eigen dashboards en evenementlogs willen maken?
Misschien wil ik een specifiek dashboard creëren voor een bedrijfs groep of een klantgericht dashboard, maar niet volledige toegang geven aan gebruikers tot de Bird UI. Dit script raakt slechts de oppervlakte van wat er mogelijk is met Python, Plotly Dash en onze API's.
Toen ik mijn zoektocht online begon, wilde ik de weg van de minste weerstand vinden. Ik had alle dashboards en UI zelf kunnen maken in HTML en Python, maar na wat zoeken op Google kwam ik Plotly's Dash tegen, dat gemakkelijk integreert met Python. Ik koos Dash om twee redenen: 1) het is open source, en 2) na het lezen van de documentatie leek het gemakkelijk aanpasbaar voor wat ik wilde doen. Dash is een open-source bibliotheek die ideaal is voor het bouwen en implementeren van data-apps met aangepaste gebruikersinterfaces. Dit maakte het creëren van een UI extreem eenvoudig. De vraag werd toen, hoe complex wilde ik deze app maken? Hoe meer tijd ik besteedde, hoe meer functies ik wilde toevoegen.
Voor het initiële project wilde ik ervoor zorgen dat ik een dashboard had met aanpasbare metrics en een selecteerbare tijdsperiode. Aanvankelijk begon ik met een dashboard waar je slechts één metric uit de dropdown kon selecteren. Toen, na feedback van collega's, verfijnde ik het dashboard een beetje om multi-select en asstitels toe te voegen. Ik besloot ook een extra tabblad voor een evenementlog toe te voegen. Ik kwam op het punt dat ik tevreden was met wat ik had als een goed startpunt voor iedereen die zijn eigen dashboards wil bouwen. Natuurlijk zette ik het project op Github voor jou om te klonen of een tak van te maken.
Aan de slag
Om toegang te krijgen tot deze app, moet je ervoor zorgen dat je Python 3.10 of hoger draait en de volgende bibliotheken installeert:
requests
dash
pandas
Vervolgens voer je je API-sleutel in App.py in en draai je de app. Het zal draaien op http://localhost:8050. Voor verdere informatie over het implementeren hiervan op een publiek toegankelijke server (zoals AWS), zie de volgende bronnen:
Maak de Dashboardpagina
Eerst initialiseer je het dataframe en het dashboard. Zonder het dashboard te initialiseren, zal er geen dashboard in de UI verschijnen.
df = pd.DataFrame({
"Count": [0,0],
"Time": [0,0]
})
fig = px.line(df,x="Time",y="Count")
Bouw dan het eerste tabblad. Dit is een combinatie van een app-callback (om te controleren welk tabblad wordt gebruikt); samen met een voorwaardelijke functie om te controleren welk tabblad momenteel is geselecteerd. De onderstaande code bouwt alleen het lege dashboard en UI-elementen (we zullen het tabblad evenementen later behandelen). De dcc-elementen zijn de Dash Core Components en de HTML Components waarmee HTML eenvoudig in de UI kan worden gebruikt.
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)"),
#Datumselectie (max datum toegestaan is ingesteld op de datum van vandaag) 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), ),
#Grafiekobject dcc.Graph( id='Emails', figure=fig )
Let op hoe eenvoudig het is om een dashboard UI met een multi-selecteerbare, doorzoekbare dropdown te maken met Dash. Om multi-select of doorzoekbaarheid uit te schakelen, kunnen de parameters voor het maken van een dropdown eenvoudig worden gewijzigd. Ik ontdekte dat het meest complexe onderdeel van dit project het opbouwen van het daadwerkelijke dataframe vanuit invoer was, evenals het krijgen van de HTML + CSS om correct in de UI te werken.
De Time Series Metrics API stelt in staat om 33 afzonderlijke metrics op te halen op basis van een datum/tijd-reeks. Je kunt dieper filteren op domeinen, campagnes, IP-pools, verzenddomeinen, subaccounts, en de precisie van tijdreeksdata specificeren. Deze extra filters samen met leverbaarheidsanalyses zouden een toekomstige verbetering van dit project kunnen zijn (foutafhandeling zou moeten worden geïmplementeerd voor klanten die geen toegang hebben tot leverbaarheidsanalyses).
Door de Metrics API te gebruiken en aan te roepen, bouw ik een dashboard uit met de geselecteerde parameters van de gebruiker en de gespecificeerde tijdsperiode. Het geïnitialiseerde dashboard wordt vervolgens bijgewerkt.
#Bouw de API-aanroep met de gegeven parameters 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(",") #Bouw een nieuw dashboard op met de nieuwe metrics en data van de bijgewerkte API-aanroep fig = px.line(new_df, x=new_df['ts'], y=value_array, labels={"value": "Count", "variable": "Metric","ts":"Date"}) fig.update_xaxes(title_text="Tijd") fig.update_yaxes(title_text="Aantal") return fig
Hieronder een voorbeeld van meerdere geselecteerde metrics en een uitgebreide tijdsperiode.
Opmerking: er zijn veel items die automatisch in de dash-grafiek zijn ingebouwd (hover, zoomen, autoschalen).
Maak de Pagina met Gegevens van de Gebeurtenissen
De pagina met gegevens van de gebeurtenissen was iets moeilijker omdat ik niet wist wat de beste manier was om alle metrics van de gebeurtenissen op een gemakkelijk leesbare manier weer te geven. Ik overwoog om filterparameters aan deze pagina toe te voegen, maar ik besloot dat dat een aanzienlijke hoeveelheid tijd aan dit project zou toevoegen, omdat de tabel dan dynamisch moest zijn (samen met het toevoegen van de parameters, callbacks, enz.). Ik besloot om alle gebeurtenissen weer te geven en de tijdstempel eerst te plaatsen (want zonder de tijdstempel eerst te plaatsen was de grafiek niet gemakkelijk te lezen). Aanvankelijk vond ik dat met alleen de rauwe HTML de tabel ongelooflijk moeilijk te lezen was. Er waren geen randen en geen kleurverschillen voor de kop versus de rijen. Om de tabel gemakkelijker te lezen te maken, kon ik CSS binnen Dash gebruiken.
Het idee voor de details van de gebeurtenissen is bijna hetzelfde als het dashboard, behalve dat ik deze keer de Events API aanroep en alle gebeurtenissen binnenhaal. Opmerking: de gegevens van de gebeurtenissen tonen alleen de 10 meest recente gebeurtenissen (met gebruik van de parameter max_rows en API-filtering). Dit kan worden verhoogd, maar ik besloot om de 10 meest recente gebeurtenissen te tonen omdat het langer duurt om de API-aanroep te doen naarmate er meer gebeurtenissen worden getoond. Een aanzienlijke verbetering die kan worden aangebracht, zou de mogelijkheid zijn om te pagineren en een Volgende Pagina / Vorige Pagina in de UI op te nemen.
Om het tabblad evenement te bouwen (pagina), roep ik eerst de Events API aan en parse de JSON-reactie naar een dataframe. Vervolgens sorteer en herorganisatie ik het dataframe om de tijdstempel als de eerste kolom te plaatsen. Ten slotte bouw ik de HTML-tabel door door het dataframe te itereren.
#Bouw en roep de Events API aan 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 #Maximaal aantal resultaten dat in de tabel met gebeurtenissen wordt weergegeven #Plaats tijdstempel als de eerste kolom in de tabel 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]] #Toon de nieuwe HTML met de tabel van gebeurtenissen (opmerking: deze tabel verwijst ook naar table.css) return html.Div([ html.H2("Details van de Gebeurtenissen"), 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)) ]) ]) ])
Die er zo uitziet in de UI.
Volgende Stappen
Voor iemand die zijn eigen dashboard of evenementlog wil maken, is dit een goed begin. Met de aanpasbaarheid hier is de lucht de grens.
Zoals hierboven besproken, zijn er enkele toekomstige verbeteringen die kunnen worden aangebracht:
Leverbaarheidsanalyses aan het dashboard toevoegen
Meer filters aan het dashboard toevoegen
Mogelijke caching-opties zodat de API niet elke keer wordt aangeroepen om de pagina's weer te geven
UI-verbeteringen
Filtering en paginering toevoegen aan de pagina met gegevens van de gebeurtenissen
Ik ben geïnteresseerd in het horen van feedback of suggesties voor het uitbreiden van dit project.
~ Zach Samuels, Bird Senior Solutions Engineer