Coverage for portality/lib/analytics.py: 0%

58 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-07-19 16:52 +0100

1# ~~ GoogleAnalytics:ExternalService~~ 

2import logging 

3import os 

4from functools import wraps 

5 

6# Logger specific to analytics 

7logger = logging.getLogger(__name__) 

8logger.setLevel(logging.DEBUG) 

9 

10# The global tracker object 

11tracker = None 

12 

13 

14class GAException(Exception): 

15 pass 

16 

17 

18def create_tracker(ga_id, domain): 

19 global tracker 

20 if ga_id: 

21 #tracker = UniversalAnalytics.Tracker.create(ga_id, client_id=domain) 

22 raise GAException("GA is not running because universal-analytics is broken in Python 3") 

23 else: 

24 raise GAException("Invalid GA ID supplied, no tracker created.") 

25 

26 

27def create_logfile(log_dir=None): 

28 filepath = __name__ + '.log' 

29 if log_dir is not None: 

30 if not os.path.exists(log_dir): 

31 os.makedirs(log_dir) 

32 filepath = os.path.join(log_dir, filepath) 

33 fh = logging.FileHandler(filepath) 

34 fh.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) 

35 logger.addHandler(fh) 

36 

37 

38class GAEvent(object): 

39 category = None 

40 action = None 

41 label = None 

42 value = None 

43 fieldsobject = None 

44 

45 def __init__(self, category, action, label='', value=None, fieldsobject=None): 

46 self.category = category 

47 self.action = action 

48 self.label = label 

49 self.value = value 

50 self.fieldsobject=fieldsobject 

51 

52 def submit(self): 

53 ga_send_event(self.category, self.action, self.label, self.value, self.fieldsobject) 

54 

55 

56def ga_send_event(category, action, label='', value=None, fieldsobject=None): 

57 """ 

58 Send event data to Google Analytics. 

59 (supposedly supporting other analytics providers as well, 

60 check https://github.com/analytics-pros/universal-analytics-python ) 

61 

62 See https://support.google.com/analytics/answer/1033068?hl=en for 

63 guidance on how to use the various event properties this decorator 

64 takes. 

65 

66 One thing to note is that event_value must be an integer. We 

67 don't really use that, it's for things like "total downloads" or 

68 "number of times video played". 

69 

70 The others are strings and can be anything we like. They must 

71 take into account what previous strings we've sent so that events 

72 can be aggregated correctly. Changing the strings you use for 

73 categories, actions and labels to describe the same event will 

74 split your analytics reports into two: before and after the 

75 change of the event strings you use. 

76 

77 :param category: Typically the object that was interacted with (e.g. 'Video') 

78 :param action: The type of interaction (e.g. 'play') 

79 :param label: Useful for categorizing events (e.g. 'Fall Campaign') 

80 :param value: A non-negative numeric value associated with the event (e.g. 42) 

81 :param fieldsobject: Key, value pairs which don't fit into the above categories 

82 """ 

83 

84 # Write event to file even if there's no tracker configured. 

85 analytics_args = [category, action] 

86 

87 if label != '': 

88 analytics_args.append(label) 

89 if value is not None: 

90 analytics_args.append(value) 

91 if fieldsobject is not None: 

92 analytics_args.append(fieldsobject) 

93 

94 logger.debug("Event Send %s", analytics_args) 

95 

96 # Send the event to GA via the tracker 

97 if tracker is not None: 

98 tracker.send('event', *analytics_args) 

99 else: 

100 # logger.error("Google Analytics tracker is not configured.") 

101 pass # we now know it's broken, stop spamming this in our logs. 

102 

103 

104def sends_ga_event(event_category, event_action, event_label='', 

105 event_value=0, record_value_of_which_arg=''): 

106 """ 

107 Decorator for Flask view functions, sending event data to Google 

108 Analytics. 

109 

110 :param event_category: 

111 :param event_action: 

112 :param event_label: 

113 :param event_value: 

114 

115 :param record_value_of_which_arg: The name of one argument that 

116 the view function takes. During tracking, the value of that 

117 argument will be extracted and sent as the Event Label to the 

118 analytics servers. NOTE! If you pass both event_label and 

119 record_value_of_which_arg to this decorator, event_label will be 

120 ignored and overwritten by the action that 

121 record_value_of_which_arg causes. 

122 

123 For example: 

124 @sends_ga_event('API Hit', 'Search applications', 

125 record_value_of_which_arg='search_query') 

126 def search_applications(search_query): 

127 # ... 

128 

129 Then we get a hit, with search_query being set to 'computer shadows'. 

130 This will result in an event with category "API Hit", action "Search 

131 applications" and label "computer shadows". 

132 

133 A different example: 

134 @sends_ga_event('API Hit', 'Retrieve application', 

135 record_value_of_which_arg='application_id') 

136 def retrieve_application(application_id): 

137 # ... 

138 

139 Then we get a hit asking for application with id '12345'. 

140 This will result in an event with category "API Hit", action "Retrieve 

141 application" and label "12345". 

142 

143 Clashing arguments: 

144 @sends_ga_event('API Hit', 'Retrieve application', 

145 event_label='Special interest action', 

146 record_value_of_which_arg='application_id') 

147 def retrieve_application(application_id): 

148 # ... 

149 

150 Then we get a hit asking for application with id '12345' again. 

151 This will result in an event with category "API Hit", action "Retrieve 

152 application" and label "12345". I.e. the event_label passed in will 

153 be ignored, because we also passed in record_value_of_which_arg which 

154 overrides the event label sent to the analytics servers. 

155 

156 On testing: this has been tested manually on DOAJ with Google 

157 Analytics by @emanuil-tolev & @Steven-Eardley. 

158 """ 

159 

160 def decorator(fn): 

161 @wraps(fn) 

162 def decorated_view(*args, **kwargs): 

163 el = event_label 

164 if record_value_of_which_arg in kwargs: 

165 el = kwargs[record_value_of_which_arg] 

166 

167 ga_send_event(event_category, event_action, el, event_value) 

168 

169 return fn(*args, **kwargs) 

170 

171 return decorated_view 

172 return decorator