[FIX] Going into production
[odoo/odoo.git] / addons / web_analytics / static / src / js / web_analytics.js
1
2 var _gaq = _gaq || [];  // asynchronous stack used by google analytics
3
4 openerp.web_analytics = function(instance) {
5
6     /*
7     *  The Web Analytics Module inserts the Google Analytics JS Snippet
8     *  at the top of the page, and sends to google an url each time the
9     *  openerp url is changed.
10     *  The pushes of the urls is made by triggering the 'state_pushed' event in the
11     *  web_client.do_push_state() method which is responsible of changing the openerp current url
12     */
13
14     // Google Analytics Code snippet
15     (function() {
16         var ga   = document.createElement('script');
17         ga.type  = 'text/javascript';
18         ga.async = true;
19         ga.src   = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
20         var s = document.getElementsByTagName('script')[0];
21         s.parentNode.insertBefore(ga,s);
22     })();
23
24     instance.web_analytics.Tracker = instance.web.Class.extend({
25         /*
26         *  This method initializes the tracker
27         */
28         init: function() {
29             /* Comment this lines when going on production, only used for testing on localhost
30             _gaq.push(['_setAccount', 'UA-35793871-1']);
31             _gaq.push(['_setDomainName', 'none']);
32             */
33
34             /* Uncomment this lines when going on production */
35             _gaq.push(['_setAccount', 'UA-7333765-1']);
36             _gaq.push(['_setDomainName', '.openerp.com']);  // Allow multi-domain
37             /**/
38         },
39         /*
40         * This method MUST be overriden by saas_demo and saas_trial in order to
41         * set the correct user type. By default, the user connected is local to the DB.
42         */
43         _get_user_type: function() {
44             return 'Local User';
45         },
46         /*
47         * This method gets the user access level, to be used as CV in GA
48         */
49         _get_user_access_level: function() {
50             if (instance.session.uid === 1) {
51                 return 'Admin User';
52             // Make the difference between portal users and anonymous users
53             } else if (instance.session.username.indexOf('@') !== -1) {
54                 if (instance.session.username.indexOf('anonymous') === -1) {
55                     return 'Portal User';
56                 } else {
57                     return 'Anonymous User';
58                 }
59             } else if (instance.session.username.indexOf('anonymous') !== -1) {
60                 return 'Anonymous User';
61             } else {
62                 return 'Normal User';
63             }
64         },
65         /*
66         * This method contains the initialization of all user-related custom variables
67         * stored in GA. Also other modules can override it to add new custom variables
68         */
69         initialize_custom: function() {
70             // Track User Access Level, Custom Variable 4 in GA with visitor level scope
71             // Values: 'Admin User', 'Normal User', 'Portal User', 'Anonymous User'
72             _gaq.push(['_setCustomVar', 4, 'User Access Level', this.user_access_level, 1]);
73
74             // Track User Type Conversion, Custom Variable 3 in GA with session level scope
75             // Values: 'Visitor', 'Demo', 'Online Trial', 'Online Paying', 'Local User'
76             _gaq.push(['_setCustomVar', 1, 'User Type Conversion', this._get_user_type(), 2]);
77
78             return instance.session.rpc("/web/webclient/version_info", {})
79                 .done(function(res) {
80                     _gaq.push(['_setCustomVar', 5, 'Version', res.server_version, 3]);
81                     return;
82                 });
83         },
84         /*
85         *  This method contains the initialization of the object and view type
86         *  as an event in GA.
87         */
88         on_state_pushed: function(state) {
89             // Track only pages corresponding to a 'normal' view of OpenERP, views
90             // related to client actions are tracked by the action manager
91             if (state.model && state.view_type) {
92                 // Track the page
93                 var url = instance.web_analytics.generateUrl({'model': state.model, 'view_type': state.view_type});
94                 this._push_event({
95                     'category': state.model,
96                     'action': state.view_type,
97                     'label': url,
98                 });
99             }
100         },
101         /*
102         * This method includes the tracker into views and managers. It can be overriden
103         * by other modules in order to extend tracking functionalities
104         */
105         include_tracker: function() {
106             var t = this;
107             // Track the events related with the creation and the  modification of records,
108             // the view type is always form
109             instance.web.FormView.include({
110                 init: function(parent, dataset, view_id, options) {
111                     this._super.apply(this, arguments);
112                     var self = this;
113                     this.on('record_created', self, function(r) {
114                         var url = instance.web_analytics.generateUrl({'model': r.model, 'view_type': 'form'});
115                         t._push_event({
116                             'category': r.model,
117                             'action': 'form',
118                             'label': url,
119                         });
120                     });
121                     this.on('record_saved', self, function(r) {
122                         var url = instance.web_analytics.generateUrl({'model': r.model, 'view_type': 'form'});
123                         t._push_event({
124                             'category': r.model,
125                             'action': 'form',
126                             'label': url,
127                         });
128                     });
129                 }
130             });
131
132             // Track client actions
133             instance.web.ActionManager.include({
134                 ir_actions_client: function (action, options) {
135                     var url = instance.web_analytics.generateUrl({'action': action.tag});
136                     var category = action.res_model || action.type;
137                     t._push_event({
138                         'category': action.res_model || action.type,
139                         'action': action.name || action.tag,
140                         'label': url,
141                     });
142                     return this._super.apply(this, arguments);
143                 },
144             });
145
146             // Track button events
147             instance.web.View.include({
148                 do_execute_action: function(action_data, dataset, record_id, on_closed) {
149                     var category = this.model || dataset.model || '';
150                     var action;
151                     if (action_data.name && _.isNaN(action_data.name-0)) {
152                         action = action_data.name;
153                     } else {
154                         action = action_data.string || action_data.special || '';
155                     }
156                     var url = instance.web_analytics.generateUrl({'model': category, 'view_type': this.view_type});
157                     t._push_event({
158                         'category': category,
159                         'action': action,
160                         'label': url,
161                     });
162                     return this._super.apply(this, arguments);
163                 },
164             });
165
166             // Track error events
167             instance.web.CrashManager.include({
168                 show_error: function(error) {
169                     var hash = window.location.hash;
170                     var params = $.deparam(hash.substr(hash.indexOf('#')+1));
171                     var options = {};
172                     if (params.model && params.view_type) {
173                         options = {'model': params.model, 'view_type': params.view_type};
174                     } else {
175                         options = {'action': params.action};
176                     }
177                     var url = instance.web_analytics.generateUrl(options);
178                     if (error.code) {
179                         t._push_event({
180                             'category': error.message,
181                             'action': error.data.fault_code,
182                             'label': url,
183                             'noninteraction': true,
184                         });
185                     } else {
186                         t._push_event({
187                             'category': error.type,
188                             'action': error.data.debug,
189                             'label': url,
190                             'noninteraction': true,
191                         });
192                     }
193                     this._super.apply(this, arguments);
194                 },
195             });
196         },
197         /*
198         * Method called in order to send _trackEvent to GA
199         */
200         _push_event: function(options) {
201             _gaq.push(['_trackEvent',
202                 options.category,
203                 options.action,
204                 options.label,
205                 options.value,
206                 options.noninteraction
207             ]);
208         },
209         /*
210         * Method called in order to send ecommerce transactions to GA
211         */
212         _push_ecommerce: function(trans_data, item_list) {
213             _gaq.push(['_addTrans',
214                 trans_data.order_id,
215                 trans_data.store_name,
216                 trans_data.total,
217                 trans_data.tax,
218                 trans_data.shipping,
219                 trans_data.city,
220                 trans_data.state
221                 trans_data.country,
222             ]);
223             _.each(item_list, function(item) {
224                 _gaq.push(['_addItem',
225                     item.order_id,
226                     item.sku,
227                     item.name,
228                     item.category,
229                     item.price,
230                     item.quantity,
231                 ]);
232             });
233             _gaq.push(['_trackTrans']);
234         },
235     });
236
237     // ----------------------------------------------------------------
238     // utility functions
239     // ----------------------------------------------------------------
240
241     instance.web_analytics.generateUrl = function(options) {
242         var url = '';
243         _.each(options, function(value, key) {
244             url += '/' + key + '=' + value;
245         });
246         return url;
247     };
248
249     instance.web_analytics.setupTracker = function(wc) {
250         var t = wc.tracker;
251         return $.when(t._get_user_access_level()).then(function(r) {
252             t.user_access_level = r;
253             t.initialize_custom().then(function() {
254                 wc.on('state_pushed', wc, t.on_state_pushed);
255                 t.include_tracker();
256             });
257         });
258     };
259
260     // Set correctly the tracker in the current instance
261     if (instance.client instanceof instance.web.WebClient) {        // not for embedded clients
262         instance.webclient.tracker = new instance.web_analytics.Tracker();
263         instance.web_analytics.setupTracker(instance.webclient);
264     } else if (!instance.client) {
265         // client does not already exists, we are in monodb mode
266         instance.web.WebClient.include({
267             start: function() {
268                 var d = this._super.apply(this, arguments);
269                 this.tracker = new instance.web_analytics.Tracker();
270                 return d;
271             },
272             show_application: function() {
273                 var self = this;
274                 instance.web_analytics.setupTracker(self).then(function() {
275                     self._super();
276                 });
277             },
278         });
279     }
280
281 };