gooddata_marketo 0.0.1

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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +131 -0
  4. data/README.md +207 -0
  5. data/bin/Gemfile +10 -0
  6. data/bin/auth.json +17 -0
  7. data/bin/main.rb +0 -0
  8. data/bin/process.rbx +541 -0
  9. data/examples/all_lead_changes.rb +119 -0
  10. data/examples/all_leads.rb +249 -0
  11. data/examples/lead_changes_to_ads.rb +63 -0
  12. data/gooddata_marketo.gemspec +24 -0
  13. data/gooddata_marketo_gem.zip +0 -0
  14. data/lib/gooddata_marketo.rb +24 -0
  15. data/lib/gooddata_marketo/adapters/rest.rb +287 -0
  16. data/lib/gooddata_marketo/client.rb +373 -0
  17. data/lib/gooddata_marketo/data/activity_types.rb +104 -0
  18. data/lib/gooddata_marketo/data/reserved_sql_keywords.rb +205 -0
  19. data/lib/gooddata_marketo/helpers/s3.rb +141 -0
  20. data/lib/gooddata_marketo/helpers/stringwizard.rb +32 -0
  21. data/lib/gooddata_marketo/helpers/table.rb +323 -0
  22. data/lib/gooddata_marketo/helpers/webdav.rb +118 -0
  23. data/lib/gooddata_marketo/loads.rb +235 -0
  24. data/lib/gooddata_marketo/models/campaigns.rb +57 -0
  25. data/lib/gooddata_marketo/models/channels.rb +30 -0
  26. data/lib/gooddata_marketo/models/child/activity.rb +104 -0
  27. data/lib/gooddata_marketo/models/child/criteria.rb +17 -0
  28. data/lib/gooddata_marketo/models/child/lead.rb +118 -0
  29. data/lib/gooddata_marketo/models/child/mobj.rb +68 -0
  30. data/lib/gooddata_marketo/models/etl.rb +75 -0
  31. data/lib/gooddata_marketo/models/leads.rb +493 -0
  32. data/lib/gooddata_marketo/models/load.rb +17 -0
  33. data/lib/gooddata_marketo/models/mobjects.rb +121 -0
  34. data/lib/gooddata_marketo/models/streams.rb +137 -0
  35. data/lib/gooddata_marketo/models/tags.rb +35 -0
  36. data/lib/gooddata_marketo/models/validate.rb +46 -0
  37. metadata +177 -0
@@ -0,0 +1,119 @@
1
+ require 'gooddata_marketo'
2
+
3
+ MARKETO_USER = ''
4
+ MARKETO_KEY = ''
5
+ MARKETO_SUBDOMAIN = ''
6
+
7
+ GOODDATA_USER = ''
8
+ GOODDATA_PASSWORD = ''
9
+ GOODDATA_PROJECT = ''
10
+
11
+ @marketo = GoodDataMarketo.connect(:user_id => MARKETO_USER, :encryption_key => MARKETO_KEY, :api_subdomain => MARKETO_SUBDOMAIN)
12
+
13
+ # The specific parameters used in the method.
14
+
15
+ #################
16
+ # #
17
+ # CONFIGURATION #
18
+ # #
19
+ #################
20
+
21
+ get_lead_changes_from_march = {
22
+ :name => 'get_lead_changes_from_march',
23
+ :type => 'leads',
24
+ :method => 'get_changes',
25
+ :arguments => {
26
+ :oldest_created_at => 'March 26th 2014',
27
+ :latest_created_at => 'March 27th 2014',
28
+ :filters => ['Merge Leads']
29
+ }
30
+ }
31
+
32
+ get_multiple_from_january = {
33
+ :name => 'get_all_leads_january',
34
+ :type => 'leads',
35
+ :method => 'get_multiple',
36
+ :arguments => {
37
+ :ids => ['23849090','23849091'], # Notice the addition of the IDS box
38
+ :type => 'IDNUM'
39
+ }
40
+ }
41
+
42
+ @queue = [get_lead_changes_from_march, get_multiple_from_january]
43
+
44
+ ###################################
45
+ # #
46
+ # DO NOT EDIT BELOW: LOAD MANAGER #
47
+ # #
48
+ ###################################
49
+
50
+
51
+ def determine_loads_state
52
+
53
+ loads = @marketo.loads(:user => GOODDATA_USER,
54
+ :pass => GOODDATA_PASSWORD,
55
+ :project => GOODDATA_PROJECT,
56
+ :marketo_client => @marketo)
57
+
58
+ if loads.available?
59
+
60
+ file = loads.available.first
61
+ load = loads.create :name => file
62
+
63
+ load.execute
64
+
65
+ # Data from the job can now be accessed ARRAY load.storage
66
+ # load.storage
67
+
68
+ # Increment the load by one day if it is time related.
69
+
70
+ case load.json[:method]
71
+
72
+ when 'get_changes'
73
+
74
+ one_day = (24*60*60)
75
+ oca = load.arguments[:oldest_created_at]
76
+ lca = load.arguments[:latest_created_at]
77
+
78
+ load.arguments[:oldest_created_at] = (Time.parse(oca) + one_day).to_s
79
+ load.arguments[:latest_created_at] = (Time.parse(lca) + one_day).to_s
80
+
81
+ # If the latest time is later then today kill the load.
82
+ if Time.parse(lca) > Time.now
83
+
84
+ load.terminate
85
+
86
+ determine_loads_state
87
+
88
+ # Otherwise save the load and resume additional loads.
89
+ else
90
+
91
+ load.save
92
+
93
+ determine_loads_state
94
+
95
+ end
96
+
97
+ when 'get_multiple'
98
+
99
+ determine_loads_state
100
+
101
+ else
102
+ raise 'Unable to determine lead type ("get_multiple"/"get_changes")!'
103
+
104
+ end
105
+
106
+ else
107
+
108
+ load = @queue.pop
109
+ loads.create load
110
+
111
+ determine_loads_state
112
+
113
+ end
114
+
115
+ end
116
+
117
+ # Run once, recursive until no loads are available.
118
+ determine_loads_state
119
+
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'gooddata_marketo'
4
+
5
+ MARKETO_USER = ""
6
+ MARKETO_KEY = ""
7
+ MARKETO_SUBDOMAIN = ''
8
+
9
+ MARKETO_AUTHORIZED_USER = ''
10
+ MARKETO_REST_SECRET = ''
11
+ MARKETO_REST_ID = ''
12
+
13
+ MARKETO_API_LIMIT = 10000 # Total number (SOAP+REST) of API calls to make in a given day.
14
+ LEAD_LIST_DUMP_CSV = 'marketo_leads_dump.csv' # Name of file to store all lead IDS.
15
+
16
+ GOODDATA_USER = 'YOU@gooddata.com'
17
+ GOODDATA_PASSWORD = ''
18
+ GOODDATA_PROJECT = ''
19
+ GOODDATA_ADS = ''
20
+
21
+ @webdav = WebDAV.new(:user => GOODDATA_USER,
22
+ :pass => GOODDATA_PASSWORD,
23
+ :project => GOODDATA_PROJECT)
24
+
25
+ @dwh = GoodData::Datawarehouse.new(GOODDATA_USER,
26
+ GOODDATA_PASSWORD,
27
+ GOODDATA_ADS)
28
+
29
+ @marketo = GoodDataMarketo.connect(:user_id => MARKETO_USER,
30
+ :encryption_key => MARKETO_KEY,
31
+ :api_subdomain => MARKETO_SUBDOMAIN,
32
+ :webdav => @webdav)
33
+
34
+ GoodDataMarketo.logging = true
35
+
36
+ ###############################
37
+ # #
38
+ # STAGE I: GET ALL LEAD IDS #
39
+ # #
40
+ ###############################
41
+ # REST API download of all available leads.
42
+
43
+ marketo.write_all_lead_ids_to_csv :file => LEAD_LIST_DUMP_CSV
44
+
45
+ ids = CSV.open(LEAD_LIST_DUMP_CSV).map { |m| m[0] }
46
+
47
+ puts "#{Time.now} => #{ids.length} imported from local CSV." if GoodDataMarketo.logging
48
+
49
+ def get_all_leads_batch batch, index
50
+
51
+
52
+ ###############################
53
+ # #
54
+ # STAGE II: CONFIGURE LOADS #
55
+ # #
56
+ ###############################
57
+ # SOAP API
58
+ # Configure additional loads as hashes, add them to @queue
59
+
60
+ get_all_leads = {
61
+ :name => "get_all_leads_chunk_#{index}",
62
+ :type => 'leads',
63
+ :method => 'get_multiple',
64
+ :arguments => {
65
+ :ids => batch, # Notice the addition of the IDS box
66
+ :type => 'IDNUM'
67
+ }
68
+ }
69
+
70
+ @lead_dump_file = get_all_leads[:name]
71
+
72
+ # If there are aditional loads, add to this array.
73
+ @queue = [get_all_leads]
74
+
75
+
76
+ ###############################
77
+ # #
78
+ # STAGE III: LOAD #
79
+ # #
80
+ ###############################
81
+ # SOAP API. No need to cofigure beyond this point.
82
+ # Loops function until no remaining jobs.
83
+
84
+ def determine_loads_state config = {}
85
+
86
+
87
+ loads = @marketo.loads(:user => GOODDATA_USER,
88
+ :pass => GOODDATA_PASSWORD,
89
+ :project => GOODDATA_PROJECT,
90
+ :marketo_client => @marketo)
91
+
92
+ if loads.available?
93
+
94
+ file = loads.available.first
95
+ load = loads.create :name => file
96
+
97
+ # Run the load from local or remote.
98
+ load.execute
99
+
100
+ # Data from the job can now be accessed ARRAY load.storage
101
+ # load.storage
102
+
103
+ # Join all of the columns from the sample to all other columns.
104
+ @columns_load_aggregate = ['sys_capture_date']
105
+ load.storage.each { |lead| @columns_load_aggregate = @columns_load_aggregate | lead.columns }
106
+ @columns_load_aggregate.map! { |column| column.downcase.gsub('-','_') }
107
+
108
+ # Set up a new Table/Automatically loads current table if exists.
109
+ table = Table.new :client => @dwh, :name => 'marketo_leads', :columns => ['id','email']
110
+
111
+ if @columns_load_aggregate.length > 0
112
+ table.merge_columns :merge_with => @columns_load_aggregate
113
+ @csv = CSV.open("#{@lead_dump_file}.csv", 'wb')
114
+ else
115
+ @csv = CSV.open("#{@lead_dump_file}.csv", 'wb')
116
+ end
117
+
118
+ updated_columns = table.columns
119
+
120
+ if @columns_load_aggregate.length > 0
121
+ @csv << updated_columns
122
+ end
123
+
124
+ count = 0
125
+ load.storage.each do |lead|
126
+
127
+ row_to_save_csv = []
128
+
129
+ row_with_columns = updated_columns.map { |column|
130
+ if lead.columns.include? column
131
+ { column => lead.values[column] }
132
+ elsif column == 'sys_capture_date'
133
+ { 'sys_capture_date' => Time.now.to_s }
134
+ else
135
+ { column => "NULL" }
136
+ end
137
+ }
138
+
139
+ row_with_columns.each { |item|
140
+ c = item.to_a.flatten
141
+ if c[1] == "NULL"
142
+ row_to_save_csv << "NULL"
143
+ else
144
+ row_to_save_csv << c[1]
145
+ end
146
+
147
+ }
148
+
149
+ count += 1
150
+ @csv << row_to_save_csv
151
+
152
+ end
153
+
154
+ # Prepare (flush) the CSV for upload.
155
+ @csv.flush
156
+
157
+ table.import_csv("#{@lead_dump_file}.csv")
158
+
159
+ puts "#{Time.now} => CSV:Rows:#{count}"
160
+ File.delete("#{@lead_dump_file}.json")
161
+ File.delete("#{@lead_dump_file}.csv")
162
+
163
+ puts "#{Time.now} => ADS:TableComplete:#{@lead_dump_file}" if GoodDataMarketo.logging
164
+
165
+ case load.json[:method]
166
+
167
+ when 'get_changes'
168
+
169
+ # Increment the load by one day if it is time related.
170
+ time_increment = (12*60*60)
171
+ oca = load.arguments[:oldest_created_at]
172
+ lca = load.arguments[:latest_created_at]
173
+
174
+ load.arguments[:oldest_created_at] = (Time.parse(oca) + time_increment).to_s
175
+ load.arguments[:latest_created_at] = (Time.parse(lca) + time_increment).to_s
176
+
177
+ # If the latest time is later then today kill the load.
178
+ if Time.parse(lca) > Time.now
179
+
180
+ load.terminate
181
+
182
+ determine_loads_state
183
+
184
+ # Otherwise save the load and resume additional loads.
185
+ else
186
+
187
+ load.save
188
+
189
+ determine_loads_state
190
+
191
+ end
192
+
193
+ when 'get_multiple'
194
+
195
+ determine_loads_state
196
+
197
+ else
198
+ raise 'Unable to determine lead type ("get_multiple"/"get_changes")!'
199
+
200
+ end
201
+
202
+ else
203
+
204
+ load = @queue.pop
205
+
206
+ if load
207
+ loads.create load
208
+ determine_loads_state
209
+ end
210
+
211
+ end
212
+
213
+ end
214
+
215
+ # Run once, recursive until no loads are available.
216
+ determine_loads_state
217
+
218
+ end
219
+
220
+ counter = 0
221
+
222
+ while ids.length > -1
223
+
224
+ counter += 1
225
+
226
+ batch = ids.slice!(1..1000)
227
+
228
+ if batch.length > 0
229
+ puts "#{Time.now} => Batch:Downloader:Length:#{batch.length} (Req:#{counter})" if GoodDataMarketo.logging
230
+ get_all_leads_batch batch, counter
231
+
232
+ CSV.open(LEAD_LIST_DUMP_CSV,'w') do |csv|
233
+ ids.each { |row| csv << [row] }
234
+ end
235
+
236
+ next
237
+
238
+ else
239
+
240
+ break
241
+
242
+ end
243
+
244
+ end
245
+
246
+ binding.pry
247
+ # table.select("SELECT * FROM #{table_name} ORDER BY id")
248
+ # SELECT * FROM marketo_leads ORDER BY id
249
+
@@ -0,0 +1,63 @@
1
+ # encoding: UTF-8
2
+ # !!! JRUBY 1.7 REQUIRED !!!
3
+
4
+ # MARKETO CONNECTOR EXAMPLE
5
+ # Gets changes for Merge Leads since March 26th 2014. Creates a table if there is not already called leads in ADS. BULK INSERTS changed leads into leads table on ADS.
6
+
7
+
8
+ require 'gooddata_marketo'
9
+
10
+ MARKETO_USER = ''
11
+ MARKETO_KEY = ''
12
+ MARKETO_SUBDOMAIN = ''
13
+
14
+ GOODDATA_USER = ''
15
+ GOODDATA_PASSWORD = ''
16
+ GOODDATA_PROJECT = ''
17
+ GOODDATA_ADS = ''
18
+
19
+ #############
20
+ # #
21
+ # MARKETO #
22
+ # #
23
+ #############
24
+
25
+ client = GoodDataMarketo.connect(:user_id => MARKETO_USER, :encryption_key => MARKETO_KEY, :api_subdomain => MARKETO_SUBDOMAIN)
26
+
27
+ changes = client.leads.get_changes(:oldest_created_at => 'March 26th 2014', :filters => ['Merge Leads'])
28
+
29
+ changed_ids = changes.map { |c| c.id }
30
+
31
+ leads = client.leads.get_multiple(:ids => changed_ids, :type => 'IDNUM')
32
+
33
+ CSV.open("tmp_leads_#{Process.pid}.csv", 'wb') do |csv|
34
+ csv << leads.first.headers
35
+ leads.each do |lead|
36
+ csv << lead.to_row
37
+ end
38
+ end
39
+
40
+ #############
41
+ # #
42
+ # ADS #
43
+ # #
44
+ #############
45
+
46
+ dwh = GoodData::Datawarehouse.new(GOODDATA_USER, GOODDATA_PASSWORD, GOODDATA_ADS)
47
+
48
+ # Set up a Table & Import BULK CSV
49
+ table = Table.new :client => dwh, :name => 'changes'
50
+ table.import_csv(file)
51
+
52
+ # File.delete(file) # Clean up
53
+
54
+ # For each change load into the leads table
55
+ count = 0
56
+
57
+ # Print the ads additions
58
+ puts 'Print tables?'
59
+ input = gets.chomp
60
+ if input == "y" || input == "yes" || input == ""
61
+ table.select("SELECT * FROM #{table_name} ORDER BY id")
62
+ end
63
+
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'gooddata_marketo'
3
+ s.version = '0.0.1'
4
+ s.date = '2015-01-01'
5
+ s.summary = "Marketo SOAP/REST wrapper to CSV/GoodData ADS"
6
+ s.description = "A gem."
7
+ s.authors = ["Patrick McConlogue"]
8
+ s.email = 'patrick.mcconlogue@gooddata.com'
9
+ s.files = `git ls-files`.split("\n")
10
+ s.homepage = 'https://github.com/thnkr/connectors/tree/master/marketo'
11
+
12
+ s.required_ruby_version = '>= 1.9.3'
13
+
14
+ s.add_development_dependency 'aws-sdk', '~> 1.61.0'
15
+ s.add_development_dependency 'rubyntlm', '~> 0.3.2'
16
+ s.add_development_dependency 'rest-client', '~> 1.7.2'
17
+ s.add_development_dependency 'pmap', '~> 1.0.2'
18
+
19
+ s.add_runtime_dependency 'savon', '= 2.8.0'
20
+ s.add_runtime_dependency 'gooddata', '= 0.6.11'
21
+ s.add_runtime_dependency 'gooddata_datawarehouse', '= 0.0.5'
22
+
23
+ s.license = 'MIT'
24
+ end