chrisle-gattica 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+ gem 'test-unit'
4
+ gem 'hpricot' #, 0.8.6
5
+ gem 'test-unit' #, 2.4.5
6
+ gem 'bundler' #, 1.0.21
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ gattica (0.6.1)
5
+ hpricot
6
+ test-unit
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ hpricot (0.8.6)
12
+ test-unit (2.4.5)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ bundler
19
+ gattica!
20
+ hpricot
21
+ test-unit
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009 Rob Cameron
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,506 @@
1
+ Gattica
2
+ =======
3
+ Gattica is an easy to use Gem for getting data from the Google Analytics API.
4
+
5
+ Features
6
+ --------
7
+ * Supports: metrics, dimensions, sorting, filters, goals, and segments.
8
+ * Handles accounts with over 1000 profiles
9
+ * Returns data as: hash, json, CSV
10
+
11
+ [How to export Google Analytics data using Ruby](
12
+ http://www.seerinteractive.com/blog/google-analytics-data-export-api-with-rubygattica/2011/02/22/) (Links to my blog post on [Seer Interactive](http://www.seerinteractive.com))
13
+
14
+ <hr />
15
+
16
+ Quick Start
17
+ ===========
18
+ Here are bare basics to get you up and running.
19
+
20
+ Installation
21
+ ------------
22
+ Add Gattica to your Gemfile
23
+
24
+ gem 'gattica', :git => 'git://github.com/chrisle/gattica.git'
25
+
26
+ Don't forget to bundle install:
27
+
28
+ $ bundle install
29
+
30
+ Login, get a list of accounts, pick an account, and get data:
31
+
32
+ # Include the gem
33
+ require 'gattica'
34
+
35
+ # Login
36
+ ga = Gattica.new({
37
+ :email => 'email@gmail.com',
38
+ :password => 'password'
39
+ })
40
+
41
+ # Get a list of accounts
42
+ accounts = ga.accounts
43
+
44
+ # Choose the first account
45
+ ga.profile_id = accounts.first.profile_id
46
+
47
+ # Get the data
48
+ data = ga.get({
49
+ :start_date => '2011-01-01',
50
+ :end_date => '2011-04-01',
51
+ :dimensions => ['month', 'year'],
52
+ :metrics => ['visits', 'bounces'],
53
+ })
54
+
55
+ # Show the data
56
+ puts data.inspect
57
+
58
+ <hr />
59
+
60
+ General Usage
61
+ =============
62
+
63
+ ### Create your Gattica object
64
+
65
+ ga = Gattica.new({ :email => 'email@gmail.com', :password => 'password' })
66
+ puts ga.token # => returns a big alpha-numeric string
67
+
68
+ ### Query for accounts you have access to
69
+
70
+ # Retrieve a list of accounts
71
+ accounts = ga.accounts
72
+
73
+ # Show information about accounts
74
+ puts "---------------------------------"
75
+ puts "Available profiles: " + accounts.count.to_s
76
+ accounts.each do |account|
77
+ puts " --> " + account.title
78
+ puts " last updated: " + account.updated.inspect
79
+ puts " web property: " + account.web_property_id
80
+ puts " profile id: " + account.profile_id.inspect
81
+ puts " goals: " + account.goals.count.inspect
82
+ end
83
+
84
+ ### Set which profile Gattica needs to use
85
+
86
+ # Tell Gattica to query profile ID 5555555
87
+ ga.profile_id = 5555555
88
+
89
+ ### Get data from Google Analytics
90
+
91
+ The Get method will get data from Google Analytics and return Gattica::DataSet type.
92
+
93
+ * Dates must be in 'YYYY-MM-DD' format.
94
+ * Dimensions and metrics can be gotten from [Google Analytics Dimensions & Metrics Reference](http://code.google.com/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html)
95
+ * You do not need to use "ga:" at the beginning of the strings.
96
+
97
+ Here's an example:
98
+
99
+ # Get the number of visitors by month from Jan 1st to April 1st.
100
+ data = ga.get({
101
+ :start_date => '2011-01-01',
102
+ :end_date => '2011-04-01',
103
+ :dimensions => ['month', 'year'],
104
+ :metrics => ['visitors']
105
+ })
106
+
107
+ <hr />
108
+
109
+ Using Dimension & Metrics
110
+ =========================
111
+
112
+ Here are some additional examples that illustrate different things you can do with dimensions and metrics.
113
+
114
+
115
+ ### Sorting
116
+
117
+ # Sorting by number of visits in descending order (most visits at the top)
118
+ data = ga.get({
119
+ :start_date => '2011-01-01',
120
+ :end_date => '2011-04-01',
121
+ :dimensions => ['month', 'year'],
122
+ :metrics => ['visits']
123
+ :sort => ['-visits'],
124
+ })
125
+
126
+ ### Limiting results
127
+
128
+ # Limit the number of results to 25.
129
+ data = ga.get({
130
+ :start_date => '2011-01-01',
131
+ :end_date => '2011-04-01',
132
+ :dimensions => ['month', 'year'],
133
+ :metrics => ['visits']
134
+ :max_results => 25
135
+ })
136
+
137
+ ### Results as a Hash
138
+
139
+ my_hash = data.to_h['points']
140
+
141
+ # =>
142
+ # [{
143
+ # "xml" => "<entry gd:etag=\"W/&quot;.... </entry>",
144
+ # "id" => "http://www.google.com/analytics/feeds/data?...",
145
+ # "updated" => Thu, 31 Mar 2011 17:00:00 -0700,
146
+ # "title" => "ga:month=01 | ga:year=2011",
147
+ # "dimensions" => [{:month=>"01"}, {:year=>"2011"}],
148
+ # "metrics" => [{:visitors=>6}]
149
+ # },
150
+ # {
151
+ # "xml" => ...
152
+ # "id" => ...
153
+ # "updated" => ...
154
+ # ...
155
+ # }]
156
+
157
+
158
+ ### JSON formatted string
159
+
160
+ # Return data as a json string. (Useful for NoSQL databases)
161
+ my_json = data.to_h['points'].to_json
162
+
163
+ # =>
164
+ # "[{
165
+ # \"xml\":\"<entry> .... </entry>\",
166
+ # \"id\":\"http://www.google.com/analytics/feeds/data? ...",
167
+ # \"updated\":\"2011-03-31T17:00:00-07:00\",
168
+ # \"title\":\"ga:month=01 | ga:year=2011\",
169
+ # \"dimensions\":[{\"month\":\"01\"},{\"year\":\"2011\"}],
170
+ # \"metrics\":[{\"visitors\":6}]
171
+ # },
172
+ # {
173
+ # \"xml\":\"<entry> .... </entry>\",
174
+ # \"id\":\"http://www.google.com/analytics/feeds/data? ...",
175
+ # ...
176
+ # }]"
177
+
178
+ ### CSV formatted string
179
+
180
+ # Return the data in CSV format. (Useful for using in Excel.)
181
+
182
+ # Short CSV will only return your dimensions and metrics:
183
+ short_csv = data.to_csv(:short)
184
+
185
+ # => "month,year,visitors\n\n01,2011, ...."
186
+
187
+ # Long CSV will get you a few additional columns:
188
+ long_csv = data.to_csv
189
+
190
+ # => "id,updated,title,month,year,visitors\n\nhttp:// ..."
191
+
192
+
193
+ ### DIY formatting
194
+
195
+ # You can work directly with the 'point' method to return data.
196
+ data.points.each do |data_point|
197
+ month = data_point.dimensions.detect { |dim| dim.key == :month }.value
198
+ year = data_point.dimensions.detect { |dim| dim.key == :year }.value
199
+ visitors = data_point.metrics.detect { |metric| metric.key == :visitors }.value
200
+ puts "#{month}/#{year} got #{visitors} visitors"
201
+ end
202
+
203
+ # =>
204
+ # 01/2011 got 34552 visitors
205
+ # 02/2011 got 36732 visitors
206
+ # 03/2011 got 45642 visitors
207
+ # 04/2011 got 44456 visitors
208
+
209
+ <hr />
210
+
211
+ Using Filter, Goals, and Segments
212
+ =========================
213
+
214
+ Learn more about filters: [Google Data feed filtering reference](http://code.google.com/apis/analytics/docs/gdata/gdataReference.html#filtering)
215
+
216
+
217
+ ### Get profiles with goals
218
+
219
+ # Get all the profiles that have goals
220
+ profiles_with_goals = accounts.select { |account| account.goals.count > 0 }
221
+
222
+ # =>
223
+ # [{
224
+ # "id" => "http://www.google.com/analytics/feeds/accounts/ga:...",
225
+ # "updated" => Mon, 16 May 2011 16:40:30 -0700,
226
+ # "title" => "Profile Title",
227
+ # "table_id" => "ga:123456",
228
+ # "account_id" => 123456,
229
+ # "account_name" => "Account name",
230
+ # "profile_id" => 123456,
231
+ # "web_property_id" => "UA-123456-3",
232
+ # "goals"=>[{
233
+ # :active => "true",
234
+ # :name => "Goal name",
235
+ # :number => 1,
236
+ # :value => 0.0
237
+ # }]
238
+ # },
239
+ # {
240
+ # "id" => "http://www.google.com/analytics/feeds/accounts/ga:...",
241
+ # "updated" => Mon, 16 May 2011 16:40:30 -0700,
242
+ # "title" => "Profile Title",
243
+ # ...
244
+ # }]
245
+
246
+ ### List available segments
247
+
248
+ # Get all the segments that are available to you
249
+ segments = ga.segments
250
+
251
+ # Segments with negative gaid are default segments from Google. Segments
252
+ # with positive gaid numbers are custom segments that you created.
253
+ # =>
254
+ # [{
255
+ # "id" => "gaid::-1",
256
+ # "name" => "All Visits",
257
+ # "definition" => " "
258
+ # },
259
+ # {
260
+ # "id" => "gaid::-2",
261
+ # "name" => "New Visitors",
262
+ # "definition" => "ga:visitorType==New Visitor"
263
+ # },
264
+ # {
265
+ # "id" => ... # more default segments
266
+ # "name" => ...
267
+ # "definition" => ...
268
+ # },
269
+ # {
270
+ # "id" => "gaid::12345678",
271
+ # "name" => "Name of segment",
272
+ # "definition" => "ga:keyword=...."
273
+ # },
274
+ # {
275
+ # "id" => ... # more custom segments
276
+ # "name" => ...
277
+ # "definition" => ...
278
+ # }]
279
+
280
+ ### Query by segment
281
+
282
+ # Return visits and bounces for mobile traffic
283
+ # (Google's default user segment gaid::-11)
284
+
285
+ mobile_traffic = ga.get({
286
+ :start_date => '2011-01-01',
287
+ :end_date => '2011-02-01',
288
+ :dimensions => ['month', 'year'],
289
+ :metrics => ['visits', 'bounces'],
290
+ :segment => ['gaid::-11']
291
+ })
292
+
293
+ ### Filtering
294
+
295
+ Filters are boolean expressions in strings. Here's an example of an equality:
296
+
297
+ # Filter by Firefox users
298
+ firefox_users = ga.get({
299
+ :start_date => '2010-01-01',
300
+ :end_date => '2011-01-01',
301
+ :dimensions => ['month', 'year'],
302
+ :metrics => ['visits', 'bounces'],
303
+ :filters => ['browser == Firefox']
304
+ })
305
+
306
+ Here's an example of greater-than:
307
+
308
+ # Filter where visits is >= 10000
309
+ lots_of_visits = ga.get({
310
+ :start_date => '2010-01-01',
311
+ :end_date => '2011-02-01',
312
+ :dimensions => ['month', 'year'],
313
+ :metrics => ['visits', 'bounces'],
314
+ :filters => ['visits >= 10000']
315
+ })
316
+
317
+ Multiple filters is an array. Currently, they are only joined by 'AND'.
318
+
319
+ # Firefox users and visits >= 10000
320
+ firefox_users_with_many_pageviews = ga.get({
321
+ :start_date => '2010-01-01',
322
+ :end_date => '2011-02-01',
323
+ :dimensions => ['month', 'year'],
324
+ :metrics => ['visits', 'bounces'],
325
+ :filters => ['browser == Firefox', 'visits >= 10000']
326
+ })
327
+
328
+
329
+ <hr />
330
+
331
+ Even More Examples!
332
+ ===============
333
+
334
+ ### Top 25 keywords that drove traffic
335
+
336
+ Output the top 25 keywords that drove traffic to your website in the first quarter of 2011.
337
+
338
+ # Get the top 25 keywords that drove traffic
339
+ data = ga.get({
340
+ :start_date => '2011-01-01',
341
+ :end_date => '2011-04-01',
342
+ :dimensions => ['keyword'],
343
+ :metrics => ['visits'],
344
+ :sort => ['-visits'],
345
+ :max_results => 25
346
+ })
347
+
348
+ # Output our results
349
+ data.points.each do |data_point|
350
+ kw = data_point.dimensions.detect { |dim| dim.key == :keyword }.value
351
+ visits = data_point.metrics.detect { |metric| metric.key == :visits }.value
352
+ puts "#{visits} visits => '#{kw}'"
353
+ end
354
+
355
+ # =>
356
+ # 19667 visits => '(not set)'
357
+ # 1677 visits => 'keyword 1'
358
+ # 178 visits => 'keyword 2'
359
+ # 165 visits => 'keyword 3'
360
+ # 161 visits => 'keyword 4'
361
+ # 112 visits => 'keyword 5'
362
+ # 105 visits => 'seo company reviews'
363
+ # ...
364
+
365
+ <hr />
366
+
367
+ Additional Options & Settings
368
+ =============================
369
+
370
+ Setting HTTP timeout
371
+ --------------------
372
+
373
+ If you have a lot of profiles in your account (like 1000+ profiles) querying for accounts may take over a minute. Net::HTTP will timeout and an exception will be raised.
374
+
375
+ To avoid this, specify a timeout when you instantiate the Gattica object:
376
+
377
+ ga = Gattica.new({
378
+ :email => 'email@gmail.com',
379
+ :password => 'password',
380
+ :timeout => 600 # Set timeout for 10 minutes!
381
+ })
382
+
383
+ The default timeout is 300 seconds (5 minutes). Change the default in: lib/gattica/settings.rb
384
+
385
+ For reference 1000 profiles with 2-5 goals each takes around 90-120 seconds.
386
+
387
+ Reusing a session token
388
+ -----------------------
389
+
390
+ You can reuse an older session if you still have the token string. Google recommends doing this to avoid authenticating over and over.
391
+
392
+
393
+ my_token = ga.token # => 'DSasdf94...'
394
+
395
+ # Sometime later, you can initialize Gattica with the same token
396
+ ga = Gattica.new({ :token => my_token })
397
+
398
+ If your token times out, you will need to re-authenticate.
399
+
400
+ Specifying your own headers
401
+ ---------------------------
402
+
403
+ Google expects a special header in all HTTP requests called 'Authorization'. Gattica handles this header automatically. If you want to specify your own you can do that when you instantiate Gattica:
404
+
405
+ ga = Gattica.new({
406
+ :token => 'DSasdf94...',
407
+ :headers => {'My-Special-Header':'my_custom_value'}
408
+ })
409
+
410
+ <hr />
411
+
412
+ History
413
+ =======
414
+
415
+ Version history
416
+ ---------------
417
+ ### 0.6.1
418
+ * Incorporated fixes by vgololobov
419
+ * Removed circular dependency
420
+ * Fixed 1.9.3 init exception https://github.com/chrisle/gattica/pull/6
421
+
422
+ ### 0.6.0
423
+ * Update to use Google Analytics v2.4 management API
424
+
425
+ TL;DR: Uses the v2.4 API now because Google deprecated <2.3.
426
+
427
+ * :) - Drop-in replacement for you.
428
+ * :) - Won't timeout anymore.
429
+ * :) - Accounts method might be faster if you have a few profiles
430
+ * :( - Accounts method is notably slower if you have >1000 profiles.
431
+
432
+ Google has changed the output of the API < 2.3. Most notable changes
433
+ were the output of what was the /management/accounts/default call. Some
434
+ of the XML changed, but most notably it didn't return everything all at
435
+ once. It used to look like this: http://bit.ly/w6Ummj
436
+
437
+ * Fixed token [deviantech]
438
+
439
+ ### 0.5.1
440
+ * Added some tests - needs more work :(
441
+
442
+ ### 0.4.7
443
+ * Removed version numbers [john mcgrath]
444
+
445
+ ### 0.4.6
446
+ * Removed monkey patch [mathieuravaux]
447
+
448
+ ### 0.4.4
449
+ * Added a configuration file to unit tests
450
+ * Removed version.rb. Not needed. (thanks John McGrath see: github.com/john)
451
+ * Migrated examples and rewrote README file
452
+
453
+ ### 0.4.3
454
+ * FIXED: Typo in start-index parameter
455
+ * Refactored Engine class into it's own file.
456
+ * Began to re-style code to wrap at 80 characters
457
+ * Added some unit tests
458
+
459
+ ### 0.4.2
460
+ * Added Ruby 1.9 support (Thanks @mathieuravaux https://github.com/mathieuravaux)
461
+ * Uses hpricot 0.8.4 now. 0.8.3 segfaults.
462
+ * Added ability to change the timeout when requesting analytics from Google
463
+ * Added the ability to use max_results
464
+
465
+ ### 0.3.2.scottp
466
+ * scottp Added Analytics API v2 header, and basic support for "segment" argument.
467
+
468
+ ### 0.3.2
469
+ * er1c updated to use standard Ruby CSV library
470
+
471
+ ### 0.3.0
472
+ * Support for filters (filters are all AND'ed together, no OR yet)
473
+
474
+ ### 0.2.1
475
+ * More robust error checking on HTTP calls
476
+ * Added to_xml to get raw XML output from Google
477
+
478
+ ### 0.2.0 / 2009-04-27
479
+ * Changed initialization format: pass a hash of options rather than individual email, password and profile_id
480
+ * Can initialize with a valid token and use that instead of requiring email/password each time
481
+ * Can initialize with your own logger object instead of having to use the default (useful if you're using with Rails, initialize with RAILS_DEFAULT_LOGGER)
482
+ * Show error if token is invalid or expired (Google returns a 401 on any HTTP call)
483
+ * Started tests
484
+
485
+ ### 0.1.4 / 2009-04-22
486
+ * Another attempt at getting the gem to build on github
487
+
488
+ ### 0.1.3 / 2009-04-22
489
+ * Getting gem to build on github
490
+
491
+ ### 0.1.2 / 2009-04-22
492
+ * Updated readme and examples, better documentation throughout
493
+
494
+ ### 0.1.1 / 2009-04-22
495
+ * When outputting as CSV, surround each piece of data with double quotes (appears pretty common for various properties (like Browser name) to contain commas
496
+
497
+ ### 0.1.0 / 2009-03-26
498
+ * Basic functionality working good. Can't use filters yet.
499
+
500
+
501
+ Maintainer history
502
+ ------------------
503
+ * [Rob Cameron](https://github.com/activenetwork/gattica) (2010)
504
+ * [Mike Rumble](https://github.com/rumble/gattica) (2010)
505
+ * [Chris Le](https://github.com/chrisle/gattica) (Current)
506
+