1:- module(bc_api_analytics, []).
5:- use_module(library(http/http_dispatch)). 6:- use_module(library(http/http_wrapper)). 7:- use_module(library(url)). 8
9:- use_module(library(arouter)). 10:- use_module(library(dict_schema)). 11
12:- use_module(bc_view). 13:- use_module(bc_api_io). 14:- use_module(bc_api_auth). 15:- use_module(bc_api_actor). 16:- use_module(bc_data_entry). 17:- use_module(bc_analytics). 18:- use_module(bc_analytics_db). 19:- use_module(bc_admin_file). 20
22
23:- route_post(api/readers/user, record_user). 24
25record_user:-
26 bc_read_by_schema(bc_analytics_user, User),
27 bc_analytics_record_user(User, UserId),
28 bc_reply_success(UserId).
29
30:- route_post(api/readers/session, record_session). 31
32record_session:-
33 bc_read_by_schema(bc_analytics_session, Session),
34 bc_analytics_record_session(Session, SessionId),
35 bc_reply_success(SessionId).
36
37:- route_post(api/readers/pageview, record_pageview). 38
39record_pageview:-
40 bc_read_by_schema(bc_analytics_pageview, Pageview),
41 bc_analytics_record_pageview(Pageview, PageviewId),
42 bc_reply_success(PageviewId).
43
44:- route_post(api/readers/pageview_extend, record_pageview_extend). 45
46record_pageview_extend:-
47 bc_read_by_schema(bc_analytics_pageview_extend, Pageview),
48 bc_analytics_record_pageview_extend(Pageview),
49 bc_reply_success(true).
50
52
53:- route_get(bc/'readers.min.js', visitor_script). 54
55visitor_script:-
56 bc_admin_send_file('js/readers.min.js').
57
58:- route_get(bc/'readers.min.js.map', visitor_script_map). 59
60visitor_script_map:-
61 bc_admin_send_file('js/readers.min.js.map').
62
64
65:- route_get(bc/'readers.image.min.js', visitor_image_script). 66
67visitor_image_script:-
68 bc_admin_send_file('js/readers.image.min.js').
69
70:- route_get(bc/'readers.image.min.js.map', visitor_image_script_map). 71
72visitor_image_script_map:-
73 bc_admin_send_file('js/readers.image.min.js.map').
74
75:- route_get(bc/'reader.png', visitor_pixel). 76
77visitor_pixel:-
78 http_current_request(Request),
79 pixel_location(Request, Location),
80 pixel_agent(Request, Agent),
81 memberchk(search(Query), Request),
82 param_or_null(u, Query, UserId),
83 param_or_null(s, Query, SessionId),
84 param_or_null(p, Query, Platform),
85 param_or_null(t, Query, Title),
86 param_or_null(e, Query, EntryId),
87 param_or_null(r, Query, Referrer),
88 Data = pixel{
89 user_id: UserId,
90 agent: Agent,
91 platform: Platform,
92 session_id: SessionId,
93 location: Location,
94 referrer: Referrer,
95 entry_id: EntryId,
96 title: Title
97 },
98 bc_analytics_record_pixel(Data),
99 bc_admin_relative(img/'reader.png', ImagePath),
100 http_reply_file(ImagePath, [
101 unsafe(true),
102 cache(false),
103 headers([ cache_control('no-cache') ])
104 ], Request).
105
106param_or_null(Name, Query, Value):-
107 memberchk(Name=Value, Query), !.
108
109param_or_null(_, _, null).
110
111pixel_location(Request, Path):-
112 memberchk(referer(Referrer), Request), !,
113 parse_url(Referrer, Attributes),
114 memberchk(path(Path), Attributes).
115
116pixel_location(_, null).
117
118pixel_agent(Request, Agent):-
119 memberchk(user_agent(Agent), Request), !.
120
121pixel_agent(_, null).
122
123:- register_schema(bc_analytics_user, _{
124 type: dict,
125 tag: user,
126 keys: _{}
127}). 128
129:- register_schema(bc_analytics_session, _{
130 type: dict,
131 tag: session,
132 keys: _{
133 user_id: atom,
134 agent: atom,
135 platform: atom
136 }
137}). 138
139:- register_schema(bc_analytics_pageview, _{
140 type: dict,
141 tag: pageview,
142 keys: _{
143 session_id: atom,
144 location: atom,
145 referrer: atom,
146 elapsed: integer,
147 entry_id: atom,
148 title: atom
149 }
150}). 151
152:- register_schema(bc_analytics_pageview_extend, _{
153 type: dict,
154 tag: pageview_extend,
155 keys: _{
156 pageview_id: atom,
157 elapsed: integer
158 }
159}). 160
162
163:- route_get(api/analytics/timeseries/From/To/Duration,
164 bc_auth, analytics_timeseries(From, To, Duration)). 165
167
168analytics_timeseries(From, To, Duration):-
169 atom_number(Duration, DurationNum),
170 parse_month(From, FromParsed),
171 parse_month(To, ToParsed),
172 bc_analytics_user_ts(FromParsed-ToParsed, DurationNum, Users),
173 bc_analytics_session_ts(FromParsed-ToParsed, DurationNum, Sessions),
174 bc_analytics_pageview_ts(FromParsed-ToParsed, DurationNum, Pageviews),
175 bc_reply_success(_{
176 users: Users,
177 sessions: Sessions,
178 pageviews: Pageviews}).
179
181
182:- route_get(api/analytics/summary/From/To/Duration,
183 bc_auth, analytics_summary(From, To, Duration)). 184
185analytics_summary(From, To, Duration):-
186 atom_number(Duration, DurationNum),
187 parse_month(From, FromParsed),
188 parse_month(To, ToParsed),
189 bc_analytics_summary(FromParsed-ToParsed,
190 DurationNum, Summary),
191 bc_reply_success(Summary).
192
194
195:- route_get(api/analytics/users/From/To/Duration/Offset/Count,
196 bc_auth, analytics_users(From, To, Duration, Offset, Count)). 197
198analytics_users(From, To, Duration, Offset, Count):-
199 atom_number(Duration, DurationNum),
200 parse_month(From, FromParsed),
201 parse_month(To, ToParsed),
202 atom_number(Offset, OffsetNum),
203 atom_number(Count, CountNum),
204 bc_analytics_users(FromParsed-ToParsed,
205 DurationNum, OffsetNum, CountNum, Users),
206 bc_reply_success(Users).
207
209
210:- route_get(api/analytics/pages/From/To/Duration,
211 bc_auth, analytics_pages(From, To, Duration)). 212
213analytics_pages(From, To, Duration):-
214 atom_number(Duration, DurationNum),
215 parse_month(From, FromParsed),
216 parse_month(To, ToParsed),
217 bc_analytics_top_pages(FromParsed-ToParsed,
218 DurationNum, Pages),
219 bc_reply_success(Pages).
220
221parse_month(Atom, (YearNum, MonthNum)):-
222 atomic_list_concat([Year, Month], -, Atom),
223 atom_number(Year, YearNum),
224 atom_number(Month, MonthNum)
HTTP handlers for managing posts */