Coder Social home page Coder Social logo

mrkt's Introduction

Mrkt

Build Status Code Climate Test Coverage Gem Version Total Downloads

This gem provides some level of abstraction to Marketo REST APIs.

Installation

Add this line to your application's Gemfile:

gem 'mrkt'

And then execute:

$ bundle

Or install it yourself as:

$ gem install mrkt

Prerequisites

Get the following from your Marketo admin:

  • hostname, i.e. '123-abc-123.mktorest.com'
  • client id, e.g. '4567e1cdf-0fae-4685-a914-5be45043f2d8'
  • client secret, e.g. '7Gn0tuiHZiDHnzeu9P14uDQcSx9xIPPt'
  • partner id, e.g. '335b1c91511b8d8b49c7bbf66f53288f16f37b60_a0147938d3135f8ddb5a75850ea3c39313fd23c4' (optional)

Usage

Create a client and authenticate

client = Mrkt::Client.new(
  host: '123-abc-123.mktorest.com',
  client_id:  '4567e1cdf-0fae-4685-a914-5be45043f2d8',
  client_secret: '7Gn0tuiHZiDHnzeu9P14uDQcSx9xIPPt',
  partner_id: '335b1c91511b8d8b49c7bbf66f53288f16f37b60_a0147938d3135f8ddb5a75850ea3c39313fd23c4' # optional 
)

If you need verbosity during troubleshooting, enable debug mode:

client = Mrkt::Client.new(
  host: '123-abc-123.mktorest.com',
  client_id:  '4567e1cdf-0fae-4685-a914-5be45043f2d8',
  client_secret: '7Gn0tuiHZiDHnzeu9P14uDQcSx9xIPPt',
  debug: true,
  logger: ::Logger.new("log/marketo.log"), # optional, defaults to Faraday default of logging to STDOUT
  log_options: {bodies: true}) # optional, defaults to Faraday default of only logging headers

Retry authentication

Since the Marketo API provides API access keys with a validity of 3600 seconds, if you are running an hourly cronjob it's possible that your subsequent call receives the same key from the previous hour, which is then immediately expired. If this is the case, you can configure the client to retry until receiving a valid key:

client = Mrkt::Client.new(
  host: '123-abc-123.mktorest.com',
  client_id:  '4567e1cdf-0fae-4685-a914-5be45043f2d8',
  client_secret: '7Gn0tuiHZiDHnzeu9P14uDQcSx9xIPPt',
  retry_authentication: true,
  retry_authentication_count: 3, # default: 3
  retry_authentication_wait_seconds: 1, # default: 0
  )

This is turned off by default.

Get leads matching an email, print their id and email

response = client.get_leads(:email, ['[email protected]'])
response[:result].each do |result|
  p "id: #{result[:id]}, email: #{result[:email]}"
end

Create/Update leads

response = client.createupdate_leads([{ email: '[email protected]', firstName: 'John' }], lookup_field: :email)
response[:result].each do |result|
  p "id: #{result[:id]}, email: #{result[:email]}"
end

Run a smart campaign on existing leads

campaign_id = 42        # this is the ID of the campaign
lead_ids    = [1, 2, 4] # these are the leads who receive the campaign
tokens      = [{        # these tokens (optional) are then passed to the campaign
                 name:  '{{my.message}}',
                 value: 'Updated message'
               }, {
                 name:  '{{my.other token}}',
                 value: 'Value for other token'
               }]
client.request_campaign(campaign_id, lead_ids, tokens) # tokens can be omited
=> { requestId: 'e42b#14272d07d78', success: true }

Run Tests

$ bundle exec rspec

Examples

Examples are in the spec/ directory.

Contributing

  1. Fork it ( https://github.com/raszi/mrkt/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

mrkt's People

Contributors

alex-wood avatar alpaca-tc avatar antonwestman avatar benjamin-ltr avatar bwebster avatar dbelling avatar dependabot[bot] avatar domenico-angilletta avatar erdostom avatar gabealmer avatar jalemieux avatar justinsoong avatar kennon avatar lpopa avatar mkmn avatar nathanhoel avatar nicolas-fricke avatar raszi avatar takuyan avatar thomasdziedzic-pd avatar tro2102 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mrkt's Issues

specifying fields in get_leads is broken

Setup:
ruby 2.4.1
mrkt 0.10.0

Problem:
When I specify fields when calling get_leads, the response doesn't include the asked for fields.

pry(main)> response = $marketo.get_leads(:email, ['REDACTED'], fields: ['phone'])
GET https://REDACTED.mktorest.com/rest/v1/leads.json?fields%5B%5D=phone&filterType=email&filterValues=REDACTED
User-Agent: "Faraday v0.15.4"
Authorization: "Bearer REDACTED"
Status 200
server: "nginx"
date: "Tue, 16 Jul 2019 23:17:18 GMT"
content-type: "application/json;charset=UTF-8"
content-length: "210"
connection: "close"
{:requestId=>"REDACTED",
 :result=>
  [{:id=>REDACTED,
    :firstName=>"REDACTED",
    :lastName=>"REDACTED",
    :email=>"REDACTED",
    :updatedAt=>"2019-06-19T12:42:38Z",
    :createdAt=>"2019-04-03T01:15:52Z"}],
 :success=>true}

=> {:requestId=>"REDACTED", :result=>[{:id=>REDACTED, :firstName=>"REDACTED", :lastName=>"REDACTED", :email=>"REDACTED", :updatedAt=>"2019-06-19T12:42:38Z", :createdAt=>"2019-04-03T01:15:52Z"}], :success=>true}

I noticed that get_lead_by_id doesn't display this behavior:

pry(main)> response = $marketo.get_lead_by_id(REDACTED, fields: ['phone'])
GET https://REDACTED.mktorest.com/rest/v1/lead/REDACTED.json?fields=phone
User-Agent: "Faraday v0.15.4"
Authorization: "Bearer REDACTED"
Status 200
server: "nginx"
date: "Tue, 16 Jul 2019 23:18:43 GMT"
content-type: "application/json;charset=UTF-8"
content-length: "94"
connection: "close"
{:requestId=>"REDACTED",
 :result=>[{:id=>REDACTED, :phone=>"REDACTED"}],
 :success=>true}

=> {:requestId=>"REDACTED", :result=>[{:id=>REDACTED, :phone=>"REDACTED"}], :success=>true}

I noticed that the difference between the 2 requests is that get_leads specifies the fields parameter with fields%5B%5D=phone (when decoded this reads fields[]=phone) while get_lead_by_id specifies the fields parameter with fields=phone`.

I also gave it a shot to see what would happen if I passed in multiple fields. Calling get_leads with fields: ['phone', 'title'] sets the url parameter to fields%5B%5D=phone&fields%5B%5D=title and doesn't return the fields in the response. Calling get_lead_by_id with fields: ['phone', 'title'] sets the url parameter to fields=phone%2Ctitle (which translates to fields=phone,title) and returns the correct fields in the response including the phone and title.

Digging into the documentation at https://developers.marketo.com/rest-api/lead-database/leads/#query I found the following relevant quote that further supports that the comma separated fields parameter is the correct way to query additional fields:

Optionally you may pass a fields parameter containing a comma-separated list of field names to return. If the fields parameter is not included in this request, the following default fields will be returned: email, updatedAt, createdAt, lastName, firstName, and id. When requesting a list of fields, if a particular field is requested, but not returned, the value is implied to be null.

root cause

I think I found the issue.
The default params encoder built into faraday encodes arrays the way get_leads encodes it: https://github.com/lostisland/faraday/blob/master/lib/faraday/encoders/nested_params_encoder.rb#L65
The reason get_lead_by_id isn't affected is because it converts the array into a string before it gets to the faraday params encoder

fields: fields&.join(',')

solutions

I think there are 2 solutions:

  1. Update get_leads to convert the fields into a string the same way get_lead_by_id does it with fields: fields&.join(','). This has the problem that we would have to remember to convert any array in the future into a string with a &.join(',').
  2. Create a custom marketo param encoder that we set on faraday. This will allow us to remove workarounds like fields&.join(',') and solve the problem for all array encoding across the mrkt gem. I found more docs about this at https://github.com/lostisland/faraday/tree/v0.15.4#changing-how-parameters-are-serialized This can be set on the connection options so that it doesn't affect any other faraday usage outside of the mrkt gem.

workarounds

A simple workaround is to just call $marketo.get_leads(:email, ['REDACTED'], fields: 'phone,title')

Update Faraday Dependency

Ideally, this should be relaxed to '< 1.0', as any backwards-incompatible change should require a major version change.

The current dependency has been out of date since Faraday 0.16 was released on September 27, 2019.

Additional Error Mappings

Running through the lib/mrkt/errors.rb mapping, I've noticed a few additional error codes that have since been added to Marketo which are not captured here - specifically codes > 1014.

I'm not sure if this library is still maintained, but I wanted to take a stab at adding support for these particular error messages, as there is some logic in an application I'm working on that relies on inspecting the error message directly for retry logic, in lieu of checking the class type on the error.

Please see the related PR #61 , and let me know if this feels sensible - thanks!

Empty results in client.get_leads by cookie

I'm attempting to find a lead id via the munchkin cookie.

When I use the client in this manner:
response = client.get_leads(:cookie, [cookie])
I get {:requestId=>"xx", :result=>[], :success=>true}

If i make a direct request with the same cookie via HTTParty
HTTParty.get('https://#{id}.mktorest.com/rest/v1/leads.json?filterType=cookie&filterValues=#{cookie}&fields=cookies,email&access_token=#{access_token}')
I also get a successful response but this time including results.

I've used the same initialized client to call get leads by email (client.get_leads(:email, [current_user.profile.email])) and that returns the correct results. Perplexed as to why this would be different or what the issue could be.

Invalid number of arguments when initializing Faraday logger

At

conn.response :logger, @logger, (@log_options || {})
, three arguments are being passed to initialize Faraday's logger but the function being called at https://github.com/lostisland/faraday/blob/v0.8.11/lib/faraday/response/logger.rb#L7 only takes two arguments. Version 0.9.1 of Faraday adds the additional argument but the gemspec for this library only has a dependency for versions of faraday-middleware which has a dependency range that includes earlier versions of Faraday that crash when provided the additional argument.

My project is currently using faraday-middleware 0.10.0 and faraday 0.8.11.

codeclimate-test-reporter is deprecated

I was checking some of the dependencies in the gem and it seems like one of the dependencies is marked deprecated by upstream.

https://github.com/codeclimate/ruby-test-reporter#codeclimate-test-reporter---deprecated

These configuration instructions refer to a language-specific test reporter who is now deprecated in favor of our new unified test reporter client. The new test reporter is faster, distributed as a static binary, has support for parallelized CI builds, and will receive ongoing support by the team here. The existing test reporters for Ruby, Python, PHP, and Javascript are now deprecated.

Link to instructions for the new test reporter: https://docs.codeclimate.com/docs/configuring-test-coverage

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.