Skip to content

Commit 9ff66d3

Browse files
Merge pull request #59 from DripEmail/shopper-activity-support
Shopper activity support
2 parents 193401f + 317537e commit 9ff66d3

6 files changed

Lines changed: 214 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
88

99
[master]: https://github.com/DripEmail/drip-ruby/compare/v3.2.0...HEAD
1010

11+
### Added
12+
- Support for the cart, order, and product endpoints in the shopper activity API.
13+
1114
### Changed
1215
- `Drip::Client#url_prefix` parameter no longer includes `/vN` part of the URL in order to prepare for Shopper Activity API. This breaks backwards compatibility for this option, but there is no expected production usage of this parameter.
1316
- `Drip::Client#get`, `Drip::Client#post`, `Drip::Client#put`, and `Drip::Client#delete` are deprecated. If you are using these to hit a Drip API endpoint, please file a ticket or PR to fix the use case.

lib/drip/client.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "drip/client/forms"
1313
require "drip/client/http_client"
1414
require "drip/client/orders"
15+
require "drip/client/shopper_activity"
1516
require "drip/client/subscribers"
1617
require "drip/client/tags"
1718
require "drip/client/webhooks"
@@ -32,6 +33,7 @@ class Client
3233
include Events
3334
include Forms
3435
include Orders
36+
include ShopperActivity
3537
include Subscribers
3638
include Tags
3739
include Webhooks
@@ -53,6 +55,9 @@ class Client
5355
JSON_API_CONTENT_TYPE = "application/vnd.api+json".freeze
5456
private_constant :JSON_API_CONTENT_TYPE
5557

58+
JSON_CONTENT_TYPE = "application/json".freeze
59+
private_constant :JSON_CONTENT_TYPE
60+
5661
def initialize(options = {})
5762
@config = Drip::Client::Configuration.new(options)
5863
yield(@config) if block_given?
@@ -81,6 +86,10 @@ def make_json_api_request(http_verb, path, options = {})
8186
make_request Drip::Request.new(http_verb, make_uri(path), options, JSON_API_CONTENT_TYPE)
8287
end
8388

89+
def make_json_request(http_verb, path, options = {})
90+
make_request Drip::Request.new(http_verb, make_uri(path), options, JSON_CONTENT_TYPE)
91+
end
92+
8493
def private_generate_resource(key, *args)
8594
# No reason for this to be part of the public API, so making a duplicate method to make it private.
8695
{ key => args }
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
module Drip
2+
class Client
3+
module ShopperActivity
4+
# Public: Create a cart activity event.
5+
#
6+
# options - Required. A Hash of additional cart options. Refer to the
7+
# Drip API docs for the required schema.
8+
#
9+
# Returns a Drip::Response.
10+
# See https://developer.drip.com/#cart-activity
11+
def create_cart_activity_event(data = {})
12+
raise ArgumentError, 'email: or person_id: parameter required' if !data.key?(:email) && !data.key?(:person_id)
13+
14+
%i[provider action cart_id cart_url].each do |key|
15+
raise ArgumentError, "#{key}: parameter required" unless data.key?(key)
16+
end
17+
18+
data[:occurred_at] = Time.now.iso8601 unless data.key?(:occurred_at)
19+
make_json_request :post, "v3/#{account_id}/shopper_activity/cart", data
20+
end
21+
22+
# Public: Create an order activity event.
23+
#
24+
# options - Required. A Hash of additional order options. Refer to the
25+
# Drip API docs for the required schema.
26+
#
27+
# Returns a Drip::Response.
28+
# See https://developer.drip.com/#order-activity
29+
def create_order_activity_event(data = {})
30+
raise ArgumentError, 'email: or person_id: parameter required' if !data.key?(:email) && !data.key?(:person_id)
31+
32+
%i[provider action order_id].each do |key|
33+
raise ArgumentError, "#{key}: parameter required" unless data.key?(key)
34+
end
35+
36+
data[:occurred_at] = Time.now.iso8601 unless data.key?(:occurred_at)
37+
make_json_request :post, "v3/#{account_id}/shopper_activity/order", data
38+
end
39+
40+
# Public: Create a product activity event.
41+
#
42+
# options - Required. A Hash of additional product options. Refer to the
43+
# Drip API docs for the required schema.
44+
#
45+
# Returns a Drip::Response.
46+
# See https://developer.drip.com/#product-activity
47+
def create_product_activity_event(data = {})
48+
%i[provider action product_id name price].each do |key|
49+
raise ArgumentError, "#{key}: parameter required" unless data.key?(key)
50+
end
51+
52+
data[:occurred_at] = Time.now.iso8601 unless data.key?(:occurred_at)
53+
make_json_request :post, "v3/#{account_id}/shopper_activity/product", data
54+
end
55+
end
56+
end
57+
end

lib/drip/response.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,20 @@ def parse_meta
4444
end
4545

4646
def parse_members
47-
if status == 429
48-
body
49-
else
50-
{}.tap do |members|
51-
if body.is_a?(Hash)
52-
body.each do |key, value|
53-
klass = if value.is_a?(Array)
54-
Drip::Collections.find_class(key)
55-
else
56-
Drip::Resources.find_class(key)
57-
end
47+
return body unless success?
48+
{}.tap do |members|
49+
if body.is_a?(Hash)
50+
body.each do |key, value|
51+
klass = case value
52+
when Array
53+
Drip::Collections.find_class(key)
54+
when String
55+
String
56+
else
57+
Drip::Resources.find_class(key)
58+
end
5859

59-
members[key] = klass.new(value)
60-
end
60+
members[key] = klass.new(value)
6161
end
6262
end
6363
end
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
require File.dirname(__FILE__) + '/../../test_helper.rb'
2+
3+
class Drip::Client::ShopperActivityTest < Drip::TestCase
4+
def setup
5+
@client = Drip::Client.new { |c| c.account_id = "12345" }
6+
end
7+
8+
context "#create_cart_activity_event" do
9+
setup do
10+
@email = "drippy@drip.com"
11+
@options = {
12+
email: @email,
13+
action: "created",
14+
provider: "shopify",
15+
cart_id: "abcdef",
16+
cart_url: "https://www.example.com/mythingy",
17+
amount: 4900,
18+
tax: 100,
19+
fees: 0,
20+
discount: 0,
21+
currency_code: "USD",
22+
properties: {
23+
"size" => "medium",
24+
"color" => "red"
25+
}
26+
}
27+
@response_status = 202
28+
@response_body = "{}"
29+
30+
stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/cart").
31+
with(headers: { "Content-Type" => "application/json" }).
32+
to_return(status: @response_status, body: @response_body, headers: {})
33+
end
34+
35+
should "send the right request" do
36+
expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
37+
assert_equal expected, @client.create_cart_activity_event(@options)
38+
end
39+
40+
should "return error when missing fields" do
41+
@options.delete(:cart_id)
42+
assert_raises(ArgumentError) { @client.create_cart_activity_event(@options) }
43+
end
44+
end
45+
46+
context "#create_order_activity_event" do
47+
setup do
48+
@email = "drippy@drip.com"
49+
@options = {
50+
email: @email,
51+
action: "created",
52+
provider: "shopify",
53+
order_id: "abcdef",
54+
amount: 4900,
55+
tax: 100,
56+
fees: 0,
57+
discount: 0,
58+
currency_code: "USD",
59+
properties: {
60+
"size" => "medium",
61+
"color" => "red"
62+
}
63+
}
64+
@response_status = 202
65+
@response_body = "{}"
66+
67+
stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/order").
68+
with(headers: { "Content-Type" => "application/json" }).
69+
to_return(status: @response_status, body: @response_body, headers: {})
70+
end
71+
72+
should "send the right request" do
73+
expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
74+
assert_equal expected, @client.create_order_activity_event(@options)
75+
end
76+
77+
should "return error when missing fields" do
78+
@options.delete(:order_id)
79+
assert_raises(ArgumentError) { @client.create_order_activity_event(@options) }
80+
end
81+
end
82+
83+
context "#create_product_activity_event" do
84+
setup do
85+
@email = "drippy@drip.com"
86+
@options = {
87+
provider: "my_custom_platform",
88+
action: "created",
89+
occurred_at: "2019-01-28T12:15:23Z",
90+
product_id: "B01J4SWO1G",
91+
product_variant_id: "B01J4SWO1G-CW-BOTT",
92+
sku: "XHB-1234",
93+
name: "The Coolest Water Bottle",
94+
brand: "Drip",
95+
categories: [
96+
"Accessories"
97+
],
98+
price: 11.16,
99+
inventory: 42,
100+
product_url: "https://mysuperstore.example.com/dp/B01J4SWO1G",
101+
image_url: "https://www.getdrip.com/images/example_products/water_bottle.png"
102+
}
103+
@response_status = 202
104+
@response_body = "{}"
105+
106+
stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/product").
107+
with(headers: { "Content-Type" => "application/json" }).
108+
to_return(status: @response_status, body: @response_body, headers: {})
109+
end
110+
111+
should "send the right request" do
112+
expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
113+
assert_equal expected, @client.create_product_activity_event(@options)
114+
end
115+
116+
should "return error when missing fields" do
117+
@options.delete(:product_id)
118+
assert_raises(ArgumentError) { @client.create_product_activity_event(@options) }
119+
end
120+
end
121+
end

test/drip/response_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ class Drip::ResponseTest < Drip::TestCase
126126
subject = Drip::Response.new(200, body)
127127
assert_equal "john@acme.com", subject.subscriber.email
128128
end
129+
130+
context "with v3 response" do
131+
setup do
132+
@body = { "request_id" => "9f119d4b-893a-4279-adb2-c920b6c2034b" }
133+
@subject = Drip::Response.new(200, @body)
134+
end
135+
136+
should "be accessible via method call" do
137+
assert_equal "9f119d4b-893a-4279-adb2-c920b6c2034b", @subject.request_id
138+
end
139+
end
129140
end
130141

131142
context "rate limit response" do

0 commit comments

Comments
 (0)