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.
- checksums.yaml +7 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +131 -0
- data/README.md +207 -0
- data/bin/Gemfile +10 -0
- data/bin/auth.json +17 -0
- data/bin/main.rb +0 -0
- data/bin/process.rbx +541 -0
- data/examples/all_lead_changes.rb +119 -0
- data/examples/all_leads.rb +249 -0
- data/examples/lead_changes_to_ads.rb +63 -0
- data/gooddata_marketo.gemspec +24 -0
- data/gooddata_marketo_gem.zip +0 -0
- data/lib/gooddata_marketo.rb +24 -0
- data/lib/gooddata_marketo/adapters/rest.rb +287 -0
- data/lib/gooddata_marketo/client.rb +373 -0
- data/lib/gooddata_marketo/data/activity_types.rb +104 -0
- data/lib/gooddata_marketo/data/reserved_sql_keywords.rb +205 -0
- data/lib/gooddata_marketo/helpers/s3.rb +141 -0
- data/lib/gooddata_marketo/helpers/stringwizard.rb +32 -0
- data/lib/gooddata_marketo/helpers/table.rb +323 -0
- data/lib/gooddata_marketo/helpers/webdav.rb +118 -0
- data/lib/gooddata_marketo/loads.rb +235 -0
- data/lib/gooddata_marketo/models/campaigns.rb +57 -0
- data/lib/gooddata_marketo/models/channels.rb +30 -0
- data/lib/gooddata_marketo/models/child/activity.rb +104 -0
- data/lib/gooddata_marketo/models/child/criteria.rb +17 -0
- data/lib/gooddata_marketo/models/child/lead.rb +118 -0
- data/lib/gooddata_marketo/models/child/mobj.rb +68 -0
- data/lib/gooddata_marketo/models/etl.rb +75 -0
- data/lib/gooddata_marketo/models/leads.rb +493 -0
- data/lib/gooddata_marketo/models/load.rb +17 -0
- data/lib/gooddata_marketo/models/mobjects.rb +121 -0
- data/lib/gooddata_marketo/models/streams.rb +137 -0
- data/lib/gooddata_marketo/models/tags.rb +35 -0
- data/lib/gooddata_marketo/models/validate.rb +46 -0
- 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
|