chrisle-gattica 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+