gooddata_marketo 0.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
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 +16 -0
  7. data/bin/main.rb +24 -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 +25 -0
  13. data/lib/gooddata_marketo/adapters/rest.rb +287 -0
  14. data/lib/gooddata_marketo/client.rb +373 -0
  15. data/lib/gooddata_marketo/data/activity_types.rb +104 -0
  16. data/lib/gooddata_marketo/data/reserved_sql_keywords.rb +205 -0
  17. data/lib/gooddata_marketo/helpers/s3.rb +141 -0
  18. data/lib/gooddata_marketo/helpers/stringwizard.rb +32 -0
  19. data/lib/gooddata_marketo/helpers/table.rb +323 -0
  20. data/lib/gooddata_marketo/helpers/webdav.rb +118 -0
  21. data/lib/gooddata_marketo/loads.rb +235 -0
  22. data/lib/gooddata_marketo/models/campaigns.rb +57 -0
  23. data/lib/gooddata_marketo/models/channels.rb +30 -0
  24. data/lib/gooddata_marketo/models/child/activity.rb +104 -0
  25. data/lib/gooddata_marketo/models/child/criteria.rb +17 -0
  26. data/lib/gooddata_marketo/models/child/lead.rb +118 -0
  27. data/lib/gooddata_marketo/models/child/mobj.rb +68 -0
  28. data/lib/gooddata_marketo/models/etl.rb +75 -0
  29. data/lib/gooddata_marketo/models/leads.rb +493 -0
  30. data/lib/gooddata_marketo/models/load.rb +17 -0
  31. data/lib/gooddata_marketo/models/mobjects.rb +121 -0
  32. data/lib/gooddata_marketo/models/streams.rb +137 -0
  33. data/lib/gooddata_marketo/models/tags.rb +35 -0
  34. data/lib/gooddata_marketo/models/validate.rb +46 -0
  35. data/lib/gooddata_marketo.rb +24 -0
  36. data/process.rb +517 -0
  37. metadata +177 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 522a33b780f99c3d01e5bec4e9e26708b754c5ab
4
+ data.tar.gz: adb50eb798055b9d6adcb74e9b5d1b76c2de0fde
5
+ SHA512:
6
+ metadata.gz: 431cd59dae68255b34126f7a047dbe81cad44620fc5059de14a5c4918b8be685ee5638a1406d75cd75c6f584c376ccf5d705cbb4f9b3805fb2347da0e76e2f1f
7
+ data.tar.gz: 21eb2af9c8ea6eb8818486885b4ce979dfc459ea554bc5ddab24d5ecf81be55d2d108af8b9519b0cdb4faeac77b7e4003f4c623272af66d17ead7a3859fec442
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'savon', '2.8.0'
4
+ gem 'rubyntlm', '0.3.2'
5
+ gem 'gooddata', '0.6.11'
6
+ gem 'rest-client', '1.7.2'
7
+ gem 'aws-sdk', '1.61.0'
8
+ gem 'pmap', '1.0.2'
9
+ gem 'gooddata_warehouse', '0.0.5'
data/Gemfile.lock ADDED
@@ -0,0 +1,131 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (4.2.0)
5
+ i18n (~> 0.7)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.3, >= 0.3.4)
9
+ tzinfo (~> 1.1)
10
+ akami (1.2.2)
11
+ gyoku (>= 0.4.0)
12
+ nokogiri
13
+ aws-sdk (1.61.0)
14
+ aws-sdk-v1 (= 1.61.0)
15
+ aws-sdk-v1 (1.61.0)
16
+ json (~> 1.4)
17
+ nokogiri (>= 1.4.4)
18
+ builder (3.2.2)
19
+ coderay (1.1.0)
20
+ docile (1.1.5)
21
+ erubis (2.7.0)
22
+ faraday (0.9.1)
23
+ multipart-post (>= 1.2, < 3)
24
+ faraday_middleware (0.9.1)
25
+ faraday (>= 0.7.4, < 0.10)
26
+ ffi (1.9.6-java)
27
+ gli (2.12.2)
28
+ gooddata (0.6.11)
29
+ activesupport (~> 4.1, >= 4.1.0)
30
+ aws-sdk (~> 1.45)
31
+ bundler (~> 1.7, >= 1.7.3)
32
+ docile (~> 1.1, >= 1.1.5)
33
+ erubis (~> 2.7, >= 2.7.0)
34
+ gli (~> 2.12, >= 2.12.2)
35
+ highline (~> 1.6, >= 1.6.21)
36
+ i18n (~> 0.6, >= 0.6.9)
37
+ json_pure (~> 1.8, >= 1.8.1)
38
+ multi_json (~> 1.10, >= 1.10.0)
39
+ parseconfig (~> 1.0, >= 1.0.4)
40
+ pmap (~> 1.0, >= 1.0.1)
41
+ pry (~> 0.9.12.6)
42
+ rest-client (~> 1.7, >= 1.7.2)
43
+ restforce (~> 1.5, >= 1.5.0)
44
+ rubyzip (~> 1.1, >= 1.1.0)
45
+ salesforce_bulk_query (~> 0.0)
46
+ terminal-table (~> 1.4, >= 1.4.5)
47
+ gyoku (1.2.2)
48
+ builder (>= 2.1.2)
49
+ hashie (3.3.2)
50
+ highline (1.6.21)
51
+ httpi (2.3.0)
52
+ rack
53
+ i18n (0.7.0)
54
+ json (1.8.2)
55
+ json (1.8.2-java)
56
+ json_pure (1.8.2)
57
+ macaddr (1.7.1)
58
+ systemu (~> 2.6.2)
59
+ method_source (0.8.2)
60
+ mime-types (1.25.1)
61
+ mini_portile (0.6.2)
62
+ minitest (5.5.0)
63
+ multi_json (1.10.1)
64
+ multipart-post (2.0.0)
65
+ netrc (0.10.2)
66
+ nokogiri (1.6.5)
67
+ mini_portile (~> 0.6.0)
68
+ nokogiri (1.6.5-java)
69
+ nori (2.4.0)
70
+ parseconfig (1.0.6)
71
+ pmap (1.0.2)
72
+ pry (0.9.12.6)
73
+ coderay (~> 1.0)
74
+ method_source (~> 0.8)
75
+ slop (~> 3.4)
76
+ pry (0.9.12.6-java)
77
+ coderay (~> 1.0)
78
+ method_source (~> 0.8)
79
+ slop (~> 3.4)
80
+ spoon (~> 0.0)
81
+ rack (1.6.0)
82
+ rest-client (1.7.2)
83
+ mime-types (>= 1.16, < 3.0)
84
+ netrc (~> 0.7)
85
+ restforce (1.5.1)
86
+ faraday (~> 0.9.0)
87
+ faraday_middleware (>= 0.8.8)
88
+ hashie (>= 1.2.0, < 4.0)
89
+ json (>= 1.7.5, < 1.9.0)
90
+ rubyntlm (0.3.2)
91
+ rubyzip (1.1.6)
92
+ salesforce_bulk_query (0.0.6)
93
+ json (~> 1.8)
94
+ xml-simple (~> 1.1)
95
+ savon (2.8.0)
96
+ akami (~> 1.2)
97
+ builder (>= 2.1.2)
98
+ gyoku (~> 1.2)
99
+ httpi (~> 2.3)
100
+ nokogiri (>= 1.4.0)
101
+ nori (~> 2.4)
102
+ uuid (~> 2.3.7)
103
+ wasabi (= 3.3.0)
104
+ slop (3.6.0)
105
+ spoon (0.0.4)
106
+ ffi
107
+ systemu (2.6.4)
108
+ terminal-table (1.4.5)
109
+ thread_safe (0.3.4)
110
+ thread_safe (0.3.4-java)
111
+ tzinfo (1.2.2)
112
+ thread_safe (~> 0.1)
113
+ uuid (2.3.7)
114
+ macaddr (~> 1.0)
115
+ wasabi (3.3.0)
116
+ httpi (~> 2.0)
117
+ mime-types (< 2.0.0)
118
+ nokogiri (>= 1.4.0)
119
+ xml-simple (1.1.4)
120
+
121
+ PLATFORMS
122
+ java
123
+ ruby
124
+
125
+ DEPENDENCIES
126
+ aws-sdk (= 1.61.0)
127
+ gooddata (= 0.6.11)
128
+ pmap (= 1.0.2)
129
+ rest-client (= 1.7.2)
130
+ rubyntlm (= 0.3.2)
131
+ savon (= 2.8.0)
data/README.md ADDED
@@ -0,0 +1,207 @@
1
+ GOODDATA MARKETO CONNECTOR
2
+ ==========================
3
+ Marketo SOAP/REST services to GoodData ADS
4
+
5
+ ## Overview
6
+ With the Marketo Connector a complete transfer of all available lead data is automatically moved *and* kept in sync with GoodData ADS. Supporting both the Marketo REST & SOAP the GoodData Marketo Connector adapts to the source data making installation as simple as entering your login information.
7
+
8
+ ### Marketo
9
+ The central concept of the Marketo API is a "Lead". Each lead contains default attributes like City or Email in addition to custom attributes added by the client. The Marketo Connector downloads and synchronizes all leads and lead changes for a given Marketo client. The connector utitlizes two main calls, *get_lead_changes* and *get_multiple_leads*, these feed into the ADS tables *marketo_changes* and *marketo_leads* respectively. For examples, take a look at the code within the *examples* directory.
10
+
11
+ ### Getting Started
12
+
13
+ 1. Install jruby `rvm install jruby` and then `rvm use jruby` (tested on jruby 1.7.16.1)
14
+ 2. [Install DSS for Ruby](https://confluence.intgdc.com/pages/viewpage.action?title=DSS+Alpha+Version+-+User+Guide&spaceKey=plat)
15
+ 3. Clone this repository.
16
+ 4. Configure authentication in bin/auth.json.
17
+ 5. Zip the the entire "bin" folder to a new zip file.
18
+ 6. Upload the zip file it as a Ruby process, schedule it to run daily, every 12 hours.
19
+
20
+ ### Configuration & Keys
21
+ To use the Marketo Connector you must have credentials for the following services.
22
+
23
+ - [Marketo REST API](http://developers.marketo.com/blog/quick-start-guide-for-marketo-rest-api/).
24
+ - [Marketo SOAP API](http://developers.marketo.com/documentation/soap/).
25
+ - [GoodData Username, Password, & Project ID](https://na1.secure.gooddata.com/account.html?clicked_trial_link=1#/registration/projectTemplate/urn%3Agooddata%3AOnboarding).
26
+ - [AWS S3](http://aws.amazon.com/s3/).
27
+
28
+ #### File Tree
29
+
30
+ ├── bin
31
+ │   ├── Gemfile
32
+ │   ├── auth.json
33
+ │   ├── main.rb
34
+ │   └── process.rbx
35
+
36
+ ├── examples
37
+ │   ├── all_lead_changes.rb
38
+ │   ├── all_leads.rb
39
+ │   └── lead_changes_to_ads.rb
40
+
41
+ ├── lib
42
+ │   ├── gooddata_marketo
43
+ │   │   ├── adapters
44
+ │   │   │   └── rest.rb
45
+ │   │   ├── client.rb
46
+ │   │   ├── data
47
+ │   │   │   ├── activity_types.rb
48
+ │   │   │   └── reserved_sql_keywords.rb
49
+ │   │   ├── helpers
50
+ │   │   │   ├── s3.rb
51
+ │   │   │   ├── stringwizard.rb
52
+ │   │   │   ├── table.rb
53
+ │   │   │   └── webdav.rb
54
+ │   │   ├── loads.rb
55
+ │   │   └── models
56
+ │   │   ├── campaigns.rb
57
+ │   │   ├── channels.rb
58
+ │   │   ├── child
59
+ │   │   │   ├── activity.rb
60
+ │   │   │   ├── criteria.rb
61
+ │   │   │   ├── lead.rb
62
+ │   │   │   └── mobj.rb
63
+ │   │   ├── etl.rb
64
+ │   │   ├── leads.rb
65
+ │   │   ├── load.rb
66
+ │   │   ├── mobjects.rb
67
+ │   │   ├── streams.rb
68
+ │   │   ├── tags.rb
69
+ │   │   └── validate.rb
70
+ │   └── gooddata_marketo.rb
71
+
72
+ └── tests
73
+ └── test.rb
74
+
75
+ ## Custom Scripts
76
+ In addition to running the main process you can also write scripts for exploration and small transformations with the Marketo API. To start, require the Marketo Connector and create a client.
77
+
78
+ require 'marketo_connector'
79
+
80
+ user = ""
81
+ key = ""
82
+ subdomain = ""
83
+
84
+ client = GoodDataMarketo.connect(:user_id => user,
85
+ :encryption_key => key,
86
+ :api_subdomain => subdomain)
87
+
88
+ From the client you can get a specific lead or a stream of ids.
89
+
90
+ lead = client.leads.get_by_email('email@email.com')
91
+ leads = client.leads.get_multiple ['23590','2930','9209'], :filters => 'Merge Leads', :type => 'IDNUM'
92
+
93
+ ## Customizing Calls
94
+ Marketo API queries can be very time consuming, in the hours or days range, before a response returns. This is why the Marketo API allows for very complex filtration options like creation date, data-type, request size etc. Filtering your queries by some level is **required** due to the size and slower speed of Marketo. Keep in mind, as of this post RUBY Processes on the GoodData platform automatically terminate after 5 hours. Setting up configuration options for the two main calls, `client.leads.get_changes` and `client.leads.get_multiple` is almost identical, you can learn more about them [here](http://developers.marketo.com/documentation/soap/getmultipleleads/).
95
+
96
+ #### Important Configurations
97
+
98
+ * ` :timeout => Int `
99
+
100
+ Specifies the amount of time before you want a call to the API to fail. Currently the library wide default is 120 which is also the the time allocated to the SAVON GEM in the initialization of the client. To go past that you will need to change the timeout when the client is first initialized.
101
+
102
+ * ` :filters => Array `
103
+
104
+ A list of activity types which are translated into the *activity_name_filters*. Due to changes in the Marketo API becareful to print these in complete form like 'Merge Leads' instead of 'MergeLeads' or 'Webpage Clicks' instead of 'webpageClicks'.
105
+
106
+ * ` :type => String `
107
+
108
+ Defines the type of your query. For instance, `:type => 'IDNUM'` would mean you are searching for data using a Marketo ID, or you might use `:type => 'EMAIL'` if you are querying using an email. In specific cases like `client.leads.get_by_id` the type is set for you.
109
+
110
+ If the given call you are looking for is not fully implemented, you can always build the complete soap request your self by calling `client.call` directly.
111
+ Outside of the authentication options, the default configuration for the client is in *marketo_connector/client.rb* under the parameter *DEFAULT_CONFIG*.
112
+
113
+ ## Leads
114
+ All calls to Marketo return objects that contain attributes. Currently the Marketo Connector supports *Lead* and *Activity* where Activity is a child of lead containing the ID and values pertaining to the lead's activity. Custom attributes can be added to leads which include values, accessing them looks like this:
115
+
116
+ leads = client.leads.get_changes :last_created_at => '12/02/2013'
117
+ lead = leads.first
118
+ custom_form = lead.attributes['c__Custom_Form']
119
+
120
+ Where `custom_form` will now contain the given value of the lead. Lead and Activity objects can also be flattened to save to CSV for parsing in the future.
121
+
122
+ lead = client.leads.get_by_email('john@smith.com')
123
+
124
+ CSV.open('leads.csv', 'wb') do |csv|
125
+
126
+ csv << lead.headers # => Incase you wanted to wanted the headers of attributes also saved to CSV.
127
+ csv << lead.to_row
128
+
129
+ end
130
+
131
+ You can also extract the activities of a given lead through `lead.activities` or changes of a given lead with `lead.changes`. For example if you wanted to write the attributes for leads which included the City 'San Francisco' to csv...
132
+
133
+ leads = client.leads.get_changes :filters => ['Email Opens', 'Merge Leads'], :lastest_created_at => '10/11/2014'
134
+
135
+ san_francisco_leads = leads.select {|lead| lead.attributes['City'] == 'San Francisco'}
136
+
137
+ CSV.open('leads.csv', 'wb') do |csv|
138
+ san_francisco_leads.each do |lead|
139
+ csv << lead.to_row
140
+ end
141
+ end
142
+
143
+ In addition, you can always work with the raw response of the lead object with `lead.raw`.
144
+
145
+ ## Streams
146
+ Specific to getMultipleLeads, getLeadChanges, getMObjects, and getLeadActivity calls, the Marketo SOAP API supports "Streams" which allow you to increment through large responses by offset stamp or stream ID (just like pagenate).
147
+ Within the client script (*lib/marketo_connector/client.rb*) are two calls, a streaming function which automatically works through APIs, building a complete object.
148
+
149
+ In the event the Marketo times out **AND** you gave specific date configurations like *:started_at => TIME* or *:oldest_created_at => TIME*, the stream will increment your calls into smaller time windows until it does receive a response within the given timeout configuration. This is helpful to insure that the most relevant data is always in a clients account. You can also deactivate this by passing the configuration symbol *:safe* and setting it to **false**.
150
+
151
+ ## Custom Objects
152
+ Marketo allows you to query the API using what it calls *criteria* which is a hash comprised of the attribute name and value with a comparison statement like *EQ* "Equals" or *LT* "Less Then". Many criteria hashes can be sent with a given request, due to the size of these queries it is also suggest that you do so but rather than forcing you to do with large arrays of criteria hashes you simply add criteria to the given *client.mobject* like so:
153
+
154
+ criteria_one = {
155
+ :attr_name => "Id", # See the types of content it can search above.
156
+ :comparison => "LE",
157
+ :attr_value => "1010"
158
+ }
159
+
160
+ >> client.mobjects.add(criteria_one)
161
+ [{:attr_name => 'Id', :comparison => 'LE', :attr_value => '1010'}]
162
+
163
+ criteria_two = {
164
+ :attr_name => "Zip", # See the types of content it can search above.
165
+ :comparison => "EQ",
166
+ :attr_value => "94104"
167
+ }
168
+
169
+ >> client.mobjects.add(criteria_two)
170
+ [{:attr_name => 'Id', :comparison => 'LE', :attr_value => '1010'}, {:attr_name => 'Zip', :comparison => 'EQ', :attr_value => '94104'}]
171
+
172
+ The data is stored in a class array which allows you to do this:
173
+
174
+ objects = client.mobjects.get
175
+
176
+ You can also make requests with one criteria hash like this:
177
+
178
+ client.mobjects.get :criteria => HASH
179
+
180
+ Finally criteria can be removed by name with: ` client.mbobjects.remove_criteria 'NAME' `.
181
+
182
+ ## Supported Calls
183
+
184
+ * [` client.leads.get_changes `](http://developers.marketo.com/documentation/soap/getleadchanges/) - Optional config. Streaming is required.
185
+
186
+ * [` client.leads.get_multiple `](http://developers.marketo.com/documentation/soap/getmultipleleads/) - Requires an query Array, optional Config.
187
+
188
+ * [` client.leads.get_lead `](http://developers.marketo.com/documentation/soap/getlead/) - Requires query String, optional config.
189
+
190
+ * [` client.mobjects `](http://developers.marketo.com/documentation/soap/getcustomobjects/) - Requires criteria to be set (See Custom Objects above)
191
+
192
+ * [` client.usage `](http://developers.marketo.com/documentation/rest/get-daily-usage/) - Requires API key to within REST config.
193
+
194
+ * [` client.channels `](http://developers.marketo.com/documentation/soap/getchannels/) - Requires query value, optional config.
195
+
196
+ * [` client.tags `](http://developers.marketo.com/documentation/soap/gettags/) - Requires the Lead email or ID for the query, optional config.
197
+
198
+ ## Custom Requests
199
+ You can call custom requests should you need want more specific control or use of a feature.
200
+
201
+ #### Direct Call
202
+ A single call is ` client.call(WEB_METHOD, MESSAGE) ` where WEB_METHOD is the specific SOAP function you are attempting to use and message is the SOAP request message (as a hash).
203
+
204
+ #### Streaming Calls
205
+ In addition for web methods that support streaming, you can using `client.stream(WEB_METHOD, MESSAGE)` to automatically iterate through either *offset* or *start_position* and return an array of results in the correct type.
206
+
207
+
data/bin/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'savon', '2.8.0'
4
+ gem 'rubyntlm', '0.3.2'
5
+ gem 'gooddata', '0.6.11'
6
+ gem 'rest-client', '1.7.2'
7
+ gem 'aws-sdk', '1.61.0'
8
+ gem 'pmap', '1.0.2'
9
+ gem 'gooddata_warehouse', '0.0.5'
10
+ gem 'gooddata_marketo', '0.0.1'
data/bin/auth.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "MARKETO_SOAP_USER" : "",
3
+ "MARKETO_SOAP_KEY" : "",
4
+ "MARKETO_REST_ID" : "",
5
+ "MARKETO_REST_SECRET" : "",
6
+ "MARKETO_SUBDOMAIN" : "123-456-789",
7
+ "MARKETO_API_LIMIT" : 10000,
8
+ "LEAD_LIST_DUMP_CSV" : "marketo_lead_dump.csv",
9
+ "GOODDATA_USER" : "you@email.com",
10
+ "GOODDATA_PASSWORD" : "",
11
+ "GOODDATA_PROJECT" : "wj82342uljb34dmz0mp92dsypuksv2j8xw5m",
12
+ "GOODDATA_ADS" : "t4d9806bbea8656285664cf0160d2342327",
13
+ "S3_PUBLIC_KEY" : "",
14
+ "S3_PRIVATE_KEY" : "",
15
+ "S3_BUCKET" : ""
16
+ }
data/bin/main.rb ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/ruby
2
+ # !!! This file is an executable, do not edit. !!!
3
+
4
+ RUBY_EXECUTABLE = 'process.rbx'
5
+
6
+ files = [RUBY_EXECUTABLE, 'Gemfile'].map { |f| File.exists? f }
7
+
8
+ raise 'ERROR: Unable to load necessary Gemfile and executable script!' unless files.all?
9
+
10
+ # Installs dependencies for the process from Gemfile
11
+ begin
12
+ system('bundle install')
13
+ rescue Exception => exp
14
+ puts 'Broke executing bundle install'
15
+ puts exp
16
+
17
+ end
18
+
19
+ # Executes ruby process with bundler.
20
+ begin
21
+ system("bundle exec ruby #{RUBY_EXECUTABLE}")
22
+ rescue Exception => exp
23
+ puts exp
24
+ end