1
1
import json
2
+ import math
2
3
import os
3
- import base64
4
- import hashlib
5
4
5
+ import cartopy
6
+ import matplotlib .cm as cm
7
+ import matplotlib .colors as colors
8
+ import matplotlib .pyplot as plt
9
+ import numpy as np
6
10
from google .analytics .data_v1beta import BetaAnalyticsDataClient
7
- from google .analytics .data_v1beta .types import DateRange , Metric , RunReportRequest
11
+ from google .analytics .data_v1beta .types import DateRange , Dimension , Metric , RunReportRequest
8
12
9
- PORTAL_ID = os .environ . get ( 'PORTAL_ID' )
10
- FOUNDATIONS_ID = os .environ . get ( 'FOUNDATIONS_ID' )
11
- COOKBOOKS_ID = os .environ . get ( 'COOKBOOKS_ID' )
13
+ PORTAL_ID = os .environ [ 'PORTAL_ID' ]
14
+ FOUNDATIONS_ID = os .environ [ 'FOUNDATIONS_ID' ]
15
+ COOKBOOKS_ID = os .environ [ 'COOKBOOKS_ID' ]
12
16
13
17
PRIVATE_KEY_ID = os .environ .get ('PRIVATE_KEY_ID' )
14
- PRIVATE_KEY = os .environ .get ('PRIVATE_KEY' ).replace ('$' ,'\n ' )
18
+ PRIVATE_KEY = os .environ .get ('PRIVATE_KEY' ).replace ('$' , '\n ' )
15
19
16
20
credentials_dict = {
17
- " type" : " service_account" ,
18
- " project_id" : " cisl-vast-pythia" ,
19
- " private_key_id" : PRIVATE_KEY_ID ,
20
- " private_key" : PRIVATE_KEY ,
21
- " client_email" : " [email protected] " ,
22
- " client_id" : " 113402578114110723940" ,
23
- " auth_uri" : " https://accounts.google.com/o/oauth2/auth" ,
24
- " token_uri" : " https://oauth2.googleapis.com/token" ,
25
- " auth_provider_x509_cert_url" : " https://www.googleapis.com/oauth2/v1/certs" ,
26
- " client_x509_cert_url" : " https://www.googleapis.com/robot/v1/metadata/x509/pythia-metrics-api%40cisl-vast-pythia.iam.gserviceaccount.com" ,
27
- " universe_domain" : " googleapis.com"
21
+ ' type' : ' service_account' ,
22
+ ' project_id' : ' cisl-vast-pythia' ,
23
+ ' private_key_id' : PRIVATE_KEY_ID ,
24
+ ' private_key' : PRIVATE_KEY ,
25
+ ' client_email' : ' [email protected] ' ,
26
+ ' client_id' : ' 113402578114110723940' ,
27
+ ' auth_uri' : ' https://accounts.google.com/o/oauth2/auth' ,
28
+ ' token_uri' : ' https://oauth2.googleapis.com/token' ,
29
+ ' auth_provider_x509_cert_url' : ' https://www.googleapis.com/oauth2/v1/certs' ,
30
+ ' client_x509_cert_url' : ' https://www.googleapis.com/robot/v1/metadata/x509/pythia-metrics-api%40cisl-vast-pythia.iam.gserviceaccount.com' ,
31
+ ' universe_domain' : ' googleapis.com' ,
28
32
}
29
33
30
34
client = BetaAnalyticsDataClient .from_service_account_info (credentials_dict )
31
35
32
36
33
- def _run_total_users_report (property_id ):
37
+ def _format_rounding (value ):
38
+ return f"{ round (value / 1000 , 1 ):.1f} K"
39
+
40
+
41
+ def run_total_users_report (property_id ):
34
42
request = RunReportRequest (
35
43
property = f'properties/{ property_id } ' ,
36
44
dimensions = [],
@@ -44,18 +52,163 @@ def _run_total_users_report(property_id):
44
52
for row in response .rows :
45
53
total_users += int (row .metric_values [0 ].value )
46
54
47
- return total_users
55
+ return _format_rounding (total_users )
56
+
57
+
58
+ def _run_top_pages_report (property_id ):
59
+ request = RunReportRequest (
60
+ property = f'properties/{ property_id } ' ,
61
+ dimensions = [Dimension (name = 'pageTitle' )],
62
+ date_ranges = [DateRange (start_date = '2020-03-31' , end_date = 'today' )],
63
+ metrics = [Metric (name = 'screenPageViews' )],
64
+ )
65
+
66
+ response = client .run_report (request )
67
+
68
+ page_views = {}
69
+ for row in response .rows :
70
+ page = row .dimension_values [0 ].value
71
+ views = int (row .metric_values [0 ].value )
72
+ page_views [page ] = views
73
+
74
+ top_10_pages = sorted (page_views .items (), key = lambda item : item [1 ], reverse = True )[:10 ]
75
+ top_10_pages_dict = {page : views for page , views in top_10_pages }
76
+
77
+ return top_10_pages_dict
78
+
79
+
80
+ def plot_top_pages (foundations_id , cookbooks_id ):
81
+ foundations_page_views = _run_top_pages_report (foundations_id )
82
+ foundations_pages = []
83
+ foundations_sorted = {k : v for k , v in sorted (foundations_page_views .items (), key = lambda item : item [1 ])}
84
+ foundations_views = foundations_sorted .values ()
85
+ for key in foundations_sorted :
86
+ newkey = key .split ('—' )[0 ]
87
+ foundations_pages .append (newkey )
88
+
89
+ cookbooks_page_views = _run_top_pages_report (cookbooks_id )
90
+ cookbooks_pages = []
91
+ cookbooks_sorted = {k : v for k , v in sorted (cookbooks_page_views .items (), key = lambda item : item [1 ])}
92
+ cookbooks_views = cookbooks_sorted .values ()
93
+ for key in cookbooks_page_views :
94
+ newkey = key .split ('—' )[0 ]
95
+ cookbooks_pages .insert (0 , newkey )
96
+
97
+ pages = cookbooks_pages + foundations_pages
98
+
99
+ fig , ax = plt .subplots ()
100
+ plt .title ('Most Popular Pages' )
101
+
102
+ views_max = int (math .ceil (max (foundations_views ) / 10000.0 )) * 10000
103
+ ax .set_xlim ([0 , views_max ])
104
+
105
+ y = np .arange (10 )
106
+ y2 = np .arange (11 , 21 )
107
+ y3 = np .append (y , y2 )
108
+
109
+ bar1 = ax .barh (y2 , foundations_views , align = 'center' , label = 'Foundations' , color = 'royalblue' )
110
+ bar2 = ax .barh (y , cookbooks_views , align = 'center' , label = 'Cookbooks' , color = 'indianred' )
111
+
112
+ ax .set_yticks (y3 , labels = pages )
113
+
114
+ ax .bar_label (bar1 , fmt = _format_rounding )
115
+ ax .bar_label (bar2 , fmt = _format_rounding )
116
+
117
+ plt .legend ()
118
+ plt .savefig ('bypage.png' , bbox_inches = 'tight' )
119
+
120
+
121
+ def _run_usersXcountry_report (foundations_id ):
122
+ request = RunReportRequest (
123
+ property = f'properties/{ foundations_id } ' ,
124
+ dimensions = [Dimension (name = 'country' )],
125
+ metrics = [Metric (name = 'activeUsers' )],
126
+ date_ranges = [DateRange (start_date = '2020-03-31' , end_date = 'today' )],
127
+ )
128
+
129
+ response = client .run_report (request )
130
+
131
+ user_by_country = {}
132
+ for row in response .rows :
133
+ country = row .dimension_values [0 ].value
134
+ users = int (row .metric_values [0 ].value )
135
+ user_by_country [country ] = user_by_country .get (country , 0 ) + users
136
+
137
+ return user_by_country
138
+
139
+
140
+ def plot_usersXcountry (foundations_id ):
141
+ users_by_country = _run_usersXcountry_report (foundations_id )
142
+
143
+ dict_api2cartopy = {
144
+ 'Tanzania' : 'United Republic of Tanzania' ,
145
+ 'United States' : 'United States of America' ,
146
+ 'Congo - Kinshasa' : 'Democratic Republic of the Congo' ,
147
+ 'Bahamas' : 'The Bahamas' ,
148
+ 'Timor-Leste' : 'East Timor' ,
149
+ 'C\u00f4 te d\u2019 Ivoire' : 'Ivory Coast' ,
150
+ 'Bosnia & Herzegovina' : 'Bosnia and Herzegovina' ,
151
+ 'Serbia' : 'Republic of Serbia' ,
152
+ 'Trinidad & Tobago' : 'Trinidad and Tobago' ,
153
+ }
154
+
155
+ for key in dict_api2cartopy :
156
+ users_by_country [dict_api2cartopy [key ]] = users_by_country .pop (key )
157
+
158
+ top_10_countries = sorted (users_by_country .items (), key = lambda item : item [1 ], reverse = True )[:10 ]
159
+ top_10_text = '\n ' .join (
160
+ f"{ country } : { _format_rounding (value )} " for i , (country , value ) in enumerate (top_10_countries )
161
+ )
162
+
163
+ fig = plt .figure (figsize = (10 , 4 ))
164
+ ax = plt .axes (projection = cartopy .crs .PlateCarree (), frameon = False )
165
+ ax .set_title ('Pythia Foundations Unique Users by Country' )
166
+
167
+ shapefile = cartopy .io .shapereader .natural_earth (category = 'cultural' , resolution = '110m' , name = 'admin_0_countries' )
168
+ reader = cartopy .io .shapereader .Reader (shapefile )
169
+ countries = reader .records ()
170
+
171
+ colormap = plt .get_cmap ('Blues' )
172
+ colormap .set_extremes (under = 'grey' )
173
+ vmax = int (math .ceil (max (users_by_country .values ()) / 100.0 )) * 100
174
+ norm = colors .LogNorm (vmin = 1 , vmax = vmax )
175
+ mappable = cm .ScalarMappable (norm = norm , cmap = colormap )
176
+
177
+ for country in countries :
178
+ country_name = country .attributes ['SOVEREIGNT' ]
179
+ if country_name in users_by_country .keys ():
180
+ facecolor = colormap ((users_by_country [country_name ] / 105 ))
181
+
182
+ ax .add_geometries (
183
+ [country .geometry ], cartopy .crs .PlateCarree (), facecolor = facecolor , edgecolor = 'white' , linewidth = 0.7
184
+ )
185
+ else :
186
+ ax .add_geometries (
187
+ [country .geometry ], cartopy .crs .PlateCarree (), facecolor = 'grey' , edgecolor = 'white' , linewidth = 0.7
188
+ )
189
+
190
+ cax = fig .add_axes ([0.1 , - 0.015 , 0.67 , 0.03 ])
191
+ fig .colorbar (mappable = mappable , cax = cax , spacing = 'uniform' , orientation = 'horizontal' , extend = 'min' )
192
+
193
+ props = dict (boxstyle = 'round' , facecolor = 'white' , edgecolor = 'white' )
194
+ ax .text (1.01 , 0.5 , top_10_text , transform = ax .transAxes , fontsize = 9 , verticalalignment = 'center' , bbox = props )
195
+
196
+ plt .tight_layout ()
197
+ plt .savefig ('bycountry.png' , bbox_inches = 'tight' )
48
198
49
199
50
200
def get_metrics ():
51
201
metrics_dict = {}
52
- metrics_dict ['Portal' ] = _run_total_users_report (str (PORTAL_ID ))
53
- metrics_dict ['Foundations' ] = _run_total_users_report (str (FOUNDATIONS_ID ))
54
- metrics_dict ['Cookbooks' ] = _run_total_users_report (str (COOKBOOKS_ID ))
55
-
202
+ metrics_dict ['Portal' ] = run_total_users_report (str (PORTAL_ID ))
203
+ metrics_dict ['Foundations' ] = run_total_users_report (str (FOUNDATIONS_ID ))
204
+ metrics_dict ['Cookbooks' ] = run_total_users_report (str (COOKBOOKS_ID ))
56
205
with open ('user_metrics.json' , 'w' ) as outfile :
57
206
json .dump (metrics_dict , outfile )
58
207
208
+ plot_top_pages (str (FOUNDATIONS_ID ), str (COOKBOOKS_ID ))
209
+
210
+ plot_usersXcountry (str (FOUNDATIONS_ID ))
211
+
59
212
60
213
if __name__ == '__main__' :
61
214
get_metrics ()
0 commit comments