customerio 5.0.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 558909b4f1cd8c6701f8c8fcce3796ab9d7321eb19038514ac9432f728035104
4
- data.tar.gz: 5787b196ae97f8ded6122dbe83ccc9f9d363b86181b4e2144595a13b1772111b
3
+ metadata.gz: 8ad688e060a453d3f02dfcdacc1407a4376fd355deb6feb6a531d4f2b9ebbad6
4
+ data.tar.gz: ea3401fa18f031f4ecb70fc79ee8817b0278294debe53f2f78adb403873f32a5
5
5
  SHA512:
6
- metadata.gz: 8105a2cd41265da49055b42e9eff7db0c0548d930a4a91871edd2458db2c0389e5c5a2e095e79f1fd453994a55614c6f621960d30ab36d5c31e2cb5fc552a6b1
7
- data.tar.gz: 74eef21394ff63ce7305a5241e23a4a74248e12a7486f268280d74bc72d8b50ec1bdf8b72717ade273b6d4dcb7d152bb49d8861c16bce5d5385eb743c899b65a
6
+ metadata.gz: 8b708a8aba7b91c3a270b2829cc7ba24cad4d72e8030f04cc266dcf97adcb9de8579f0fe159eeed5c95669890dd30376f05c28b43540894feb8dd15f25a516d4
7
+ data.tar.gz: 128500f502747de7b3d4e92a201ebcf23fa2ebe731f529fb57d72f2919f95f81f3cb8e59917a621e9e475c957c234302641581415d21cfa2189d3aa994889557
@@ -6,7 +6,7 @@ jobs:
6
6
  test:
7
7
  strategy:
8
8
  matrix:
9
- ruby: ['2.5', '2.6', '2.7']
9
+ ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
10
10
  runs-on: ubuntu-latest
11
11
  env:
12
12
  BUNDLE_PATH: ${{ github.workspace }}/vendor/bundle
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,11 @@
1
+ ## Customerio 5.2.0 - December 8, 2023
2
+ ### Changed
3
+ - The `identify` method will now automatically use the `cio_id` attribute as the customer ID when calling the track service. This allows a customer to be updated using `identify` to modify the `id` and `email` attributes.
4
+
5
+ ## Customerio 5.1.0 - May 5, 2023
6
+ ### Added
7
+ - Added `send_push` to `APIClient` and `SendPushRequest` to support sending transactional push notifications.
8
+
1
9
  ## Customerio 4.3.1 - January 5, 2023
2
10
  ### Added
3
11
  - Added the `disable_css_preprocessing` and `language` optional fields to send request
data/README.md CHANGED
@@ -77,7 +77,7 @@ if you pass along the current subscription plan (free / basic / premium) for you
77
77
  set up triggers which are only sent to customers who have subscribed to a
78
78
  particular plan (e.g. "premium").
79
79
 
80
- You'll want to indentify your customers when they sign up for your app and any time their
80
+ You'll want to identify your customers when they sign up for your app and any time their
81
81
  key information changes. This keeps [Customer.io](https://customer.io) up to date with your customer information.
82
82
 
83
83
  ```ruby
@@ -95,6 +95,24 @@ $customerio.identify(
95
95
  )
96
96
  ```
97
97
 
98
+ ### Updating customers
99
+
100
+ You can use the identify operation to update customers.
101
+ If you need to change the `id` or `email` identifiers for a customer,
102
+ you will need to pass in the `cio_id` identifier.
103
+ `cio_id` is a unique identifier set by Customer.io, used to reference a person,
104
+ and cannot be changed.
105
+
106
+ E.g.: if the customer created in the identify operation above was given the `cio_id` of `"f000000d"`, you could change its ID and email address using:
107
+
108
+ ```ruby
109
+ $customerio.identify(
110
+ :cio_id => "f000000d",
111
+ :id => 1005,
112
+ :email => "bob.fullname@example.com"
113
+ )
114
+ ```
115
+
98
116
  ### Deleting customers
99
117
 
100
118
  Deleting a customer will remove them, and all their information from
@@ -217,7 +235,9 @@ $customerio.unsuppress(5)
217
235
 
218
236
  ### Send Transactional Messages
219
237
 
220
- To use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [app key](https://customer.io/docs/managing-credentials#app-api-keys).
238
+ To use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [app key](https://customer.io/docs/managing-credentials#app-api-keys) and create a request object of your message type.
239
+
240
+ #### Email
221
241
 
222
242
  Create a new `SendEmailRequest` object containing:
223
243
 
@@ -262,6 +282,44 @@ rescue Customerio::InvalidResponse => e
262
282
  end
263
283
  ```
264
284
 
285
+ #### Push
286
+
287
+ Create a new `SendPushRequest` object containing:
288
+
289
+ * `transactional_message_id`: the ID or trigger name of the transactional message you want to send.
290
+ * an `identifiers` object containing the `id` or `email` of your recipient. If the profile does not exist, Customer.io creates it.
291
+
292
+ Use `send_push` referencing your request to send a transactional message. [Learn more about transactional messages and `SendPushRequest` properties](https://customer.io/docs/transactional-api).
293
+
294
+
295
+ ```ruby
296
+ require "customerio"
297
+
298
+ client = Customerio::APIClient.new("your API key", region: Customerio::Regions::US)
299
+
300
+ request = Customerio::SendPushRequest.new(
301
+ transactional_message_id: "3",
302
+ message_data: {
303
+ name: "Person",
304
+ items: {
305
+ name: "shoes",
306
+ price: "59.99",
307
+ },
308
+ products: [],
309
+ },
310
+ identifiers: {
311
+ id: "2",
312
+ },
313
+ )
314
+
315
+ begin
316
+ response = client.send_push(request)
317
+ puts response
318
+ rescue Customerio::InvalidResponse => e
319
+ puts e.code, e.message
320
+ end
321
+ ```
322
+
265
323
  ## Contributing
266
324
 
267
325
  1. Fork it
@@ -26,10 +26,29 @@ module Customerio
26
26
  end
27
27
  end
28
28
 
29
+ def send_push(req)
30
+ raise "request must be an instance of Customerio::SendPushRequest" unless req.is_a?(Customerio::SendPushRequest)
31
+ response = @client.request(:post, send_push_path, req.message)
32
+
33
+ case response
34
+ when Net::HTTPSuccess then
35
+ JSON.parse(response.body)
36
+ when Net::HTTPBadRequest then
37
+ json = JSON.parse(response.body)
38
+ raise Customerio::InvalidResponse.new(response.code, json['meta']['error'], response)
39
+ else
40
+ raise InvalidResponse.new(response.code, response.body)
41
+ end
42
+ end
43
+
29
44
  private
30
45
 
31
46
  def send_email_path
32
47
  "/v1/send/email"
33
48
  end
49
+
50
+ def send_push_path
51
+ "/v1/send/push"
52
+ end
34
53
  end
35
54
  end
@@ -151,9 +151,17 @@ module Customerio
151
151
 
152
152
  def create_or_update(attributes = {})
153
153
  attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
154
- raise MissingIdAttributeError.new("Must provide a customer id") if is_empty?(attributes[:id])
154
+ if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id])
155
+ raise MissingIdAttributeError.new("Must provide a customer id")
156
+ end
155
157
 
156
- url = customer_path(attributes[:id])
158
+ # Use cio_id as the identifier, if present,
159
+ # to allow the id and email identifiers to be updated.
160
+ customer_id = attributes[:id]
161
+ if !is_empty?(attributes[:cio_id])
162
+ customer_id = "cio_" + attributes[:cio_id]
163
+ end
164
+ url = customer_path(customer_id)
157
165
  @client.request_and_verify_response(:put, url, attributes)
158
166
  end
159
167
 
@@ -55,7 +55,7 @@ module Customerio
55
55
  param
56
56
  end
57
57
 
58
- # Prefer ERB::Util.url_encode, fall baack to deprecation URI.encode for
58
+ # Prefer ERB::Util.url_encode, fall back to deprecation URI.encode for
59
59
  # old Ruby support
60
60
  def self.escape_value(value)
61
61
  if ERB::Util.respond_to? :url_encode
@@ -0,0 +1,36 @@
1
+ module Customerio
2
+ class SendPushRequest
3
+ attr_reader :message
4
+
5
+ def initialize(opts)
6
+ @message = opts.delete_if { |field| invalid_field?(field) }
7
+ @message[:custom_device] = opts[:device] if opts[:device]
8
+ end
9
+
10
+ private
11
+
12
+ REQUIRED_FIELDS = %i(transactional_message_id identifiers)
13
+
14
+ OPTIONAL_FIELDS = %i(
15
+ to
16
+ title
17
+ message
18
+ disable_message_retention
19
+ send_to_unsubscribed
20
+ queue_draft
21
+ message_data
22
+ send_at
23
+ language
24
+ image_url
25
+ link
26
+ sound
27
+ custom_data
28
+ device
29
+ custom_device
30
+ )
31
+
32
+ def invalid_field?(field)
33
+ !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module Customerio
2
- VERSION = "5.0.0"
2
+ VERSION = "5.2.0"
3
3
  end
data/lib/customerio.rb CHANGED
@@ -5,6 +5,7 @@ module Customerio
5
5
  require "customerio/base_client"
6
6
  require "customerio/client"
7
7
  require "customerio/requests/send_email_request"
8
+ require "customerio/requests/send_push_request"
8
9
  require "customerio/api"
9
10
  require "customerio/param_encoder"
10
11
  end
@@ -6,7 +6,7 @@ require 'tempfile'
6
6
  describe Customerio::APIClient do
7
7
  let(:app_key) { "appkey" }
8
8
 
9
- let(:client) { Customerio::APIClient.new(app_key) }
9
+ let(:client) { Customerio::APIClient.new(app_key) }
10
10
  let(:response) { double("Response", code: 200) }
11
11
 
12
12
  def api_uri(path)
@@ -169,4 +169,87 @@ describe Customerio::APIClient do
169
169
  req.message[:attachments].should eq({ "test" => Base64.strict_encode64("test-content") })
170
170
  end
171
171
  end
172
+
173
+ describe "#send_push" do
174
+ it "sends a POST request to the /api/send/push path" do
175
+ req = Customerio::SendPushRequest.new(
176
+ identifiers: {
177
+ id: 'c1',
178
+ },
179
+ transactional_message_id: 1,
180
+ )
181
+
182
+ stub_request(:post, api_uri('/v1/send/push'))
183
+ .with(headers: request_headers, body: req.message)
184
+ .to_return(status: 200, body: { delivery_id: 1 }.to_json, headers: {})
185
+
186
+ client.send_push(req).should eq({ "delivery_id" => 1 })
187
+ end
188
+
189
+ it "handles validation failures (400)" do
190
+ req = Customerio::SendPushRequest.new(
191
+ identifiers: {
192
+ id: 'c1',
193
+ },
194
+ transactional_message_id: 1,
195
+ )
196
+
197
+ err_json = { meta: { error: "example error" } }.to_json
198
+
199
+ stub_request(:post, api_uri('/v1/send/push'))
200
+ .with(headers: request_headers, body: req.message)
201
+ .to_return(status: 400, body: err_json, headers: {})
202
+
203
+ lambda { client.send_push(req) }.should(
204
+ raise_error(Customerio::InvalidResponse) { |error|
205
+ error.message.should eq "example error"
206
+ error.code.should eq "400"
207
+ }
208
+ )
209
+ end
210
+
211
+ it "handles other failures (5xx)" do
212
+ req = Customerio::SendPushRequest.new(
213
+ identifiers: {
214
+ id: 'c1',
215
+ },
216
+ transactional_message_id: 1,
217
+ )
218
+
219
+ stub_request(:post, api_uri('/v1/send/push'))
220
+ .with(headers: request_headers, body: req.message)
221
+ .to_return(status: 500, body: "Server unavailable", headers: {})
222
+
223
+ lambda { client.send_push(req) }.should(
224
+ raise_error(Customerio::InvalidResponse) { |error|
225
+ error.message.should eq "Server unavailable"
226
+ error.code.should eq "500"
227
+ }
228
+ )
229
+ end
230
+
231
+ it "sets custom_device correctly if device present in req" do
232
+ req = Customerio::SendPushRequest.new(
233
+ identifiers: {
234
+ id: 'c1',
235
+ },
236
+ transactional_message_id: 1,
237
+ device: {
238
+ platform: 'ios',
239
+ token: 'sample-token',
240
+ }
241
+ )
242
+
243
+ req.message[:custom_device].should eq({
244
+ platform: 'ios',
245
+ token: 'sample-token',
246
+ })
247
+
248
+ stub_request(:post, api_uri('/v1/send/push'))
249
+ .with(headers: request_headers, body: req.message)
250
+ .to_return(status: 200, body: { delivery_id: 2 }.to_json, headers: {})
251
+
252
+ client.send_push(req).should eq({ "delivery_id" => 2 })
253
+ end
254
+ end
172
255
  end
data/spec/client_spec.rb CHANGED
@@ -172,6 +172,7 @@ describe Customerio::Client do
172
172
  it "requires an id attribute" do
173
173
  lambda { client.identify(email: "customer@example.com") }.should raise_error(Customerio::Client::MissingIdAttributeError)
174
174
  lambda { client.identify(id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
175
+ lambda { client.identify(cio_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
175
176
  end
176
177
 
177
178
  it 'should not raise errors when attribute keys are strings' do
@@ -183,6 +184,45 @@ describe Customerio::Client do
183
184
 
184
185
  lambda { client.identify(attributes) }.should_not raise_error()
185
186
  end
187
+
188
+ it 'uses cio_id for customer id, when present, for id updates' do
189
+ stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
190
+ body: {
191
+ cio_id: "347f00d",
192
+ id: 5
193
+ }).to_return(status: 200, body: "", headers: {})
194
+
195
+ client.identify({
196
+ cio_id: "347f00d",
197
+ id: 5
198
+ })
199
+ end
200
+
201
+ it 'uses cio_id for customer id, when present, for email updates' do
202
+ stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
203
+ body: {
204
+ cio_id: "347f00d",
205
+ email: "different.customer@example.com"
206
+ }).to_return(status: 200, body: "", headers: {})
207
+
208
+ client.identify({
209
+ cio_id: "347f00d",
210
+ email: "different.customer@example.com"
211
+ })
212
+ end
213
+
214
+ it 'allows updates with cio_id as the only id' do
215
+ stub_request(:put, api_uri('/api/v1/customers/cio_347f00d')).with(
216
+ body: {
217
+ cio_id: "347f00d",
218
+ location: "here"
219
+ }).to_return(status: 200, body: "", headers: {})
220
+
221
+ client.identify({
222
+ cio_id: "347f00d",
223
+ location: "here"
224
+ })
225
+ end
186
226
  end
187
227
 
188
228
  describe "#delete" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: customerio
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Allison
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-30 00:00:00.000000000 Z
11
+ date: 2023-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -117,6 +117,7 @@ files:
117
117
  - lib/customerio/param_encoder.rb
118
118
  - lib/customerio/regions.rb
119
119
  - lib/customerio/requests/send_email_request.rb
120
+ - lib/customerio/requests/send_push_request.rb
120
121
  - lib/customerio/version.rb
121
122
  - spec/api_client_spec.rb
122
123
  - spec/base_client_spec.rb
@@ -126,7 +127,7 @@ homepage: http://customer.io
126
127
  licenses:
127
128
  - MIT
128
129
  metadata: {}
129
- post_install_message:
130
+ post_install_message:
130
131
  rdoc_options: []
131
132
  require_paths:
132
133
  - lib
@@ -141,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
142
  - !ruby/object:Gem::Version
142
143
  version: '0'
143
144
  requirements: []
144
- rubygems_version: 3.0.3.1
145
- signing_key:
145
+ rubygems_version: 3.2.33
146
+ signing_key:
146
147
  specification_version: 4
147
148
  summary: A ruby client for the Customer.io event API.
148
149
  test_files: