customerio 5.2.0 → 5.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ad688e060a453d3f02dfcdacc1407a4376fd355deb6feb6a531d4f2b9ebbad6
4
- data.tar.gz: ea3401fa18f031f4ecb70fc79ee8817b0278294debe53f2f78adb403873f32a5
3
+ metadata.gz: 315eb46a7117b5e0408a57f896c49bf7336003db16439780d119ddc8e4015a1a
4
+ data.tar.gz: 41ddd049e7978bb75e8c792dda18090e9ffe7e64a85079a2e4d56cbc097feb48
5
5
  SHA512:
6
- metadata.gz: 8b708a8aba7b91c3a270b2829cc7ba24cad4d72e8030f04cc266dcf97adcb9de8579f0fe159eeed5c95669890dd30376f05c28b43540894feb8dd15f25a516d4
7
- data.tar.gz: 128500f502747de7b3d4e92a201ebcf23fa2ebe731f529fb57d72f2919f95f81f3cb8e59917a621e9e475c957c234302641581415d21cfa2189d3aa994889557
6
+ metadata.gz: 895cf3b64c4f57ed636a2a80c7c356eb4387edd2f5c5c65d1d46b0a418330333f84f66407ef8d844adeeda13d6089ee00d3ce60d22790d17fa246622c291f9d9
7
+ data.tar.gz: f213766bfb67f9ad8d570292816bba51e7c6863fbcc15d98e4f1f75d80953b00813e9c531c5b84d013f5531e23f4f623dbe77e5d054ea1ccc125608ef00a343b
@@ -6,13 +6,13 @@ jobs:
6
6
  test:
7
7
  strategy:
8
8
  matrix:
9
- ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
9
+ ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
10
10
  runs-on: ubuntu-latest
11
11
  env:
12
12
  BUNDLE_PATH: ${{ github.workspace }}/vendor/bundle
13
13
  steps:
14
- - uses: actions/checkout@v2
15
- - uses: ruby/setup-ruby@v1
14
+ - uses: actions/checkout@v4
15
+ - uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1.229.0
16
16
  with:
17
17
  ruby-version: ${{ matrix.ruby }}
18
18
  bundler-cache: true
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,12 @@
1
+ ## Customerio 5.4.0 - June 13, 2025
2
+ ### Changed
3
+ - Added `send_sms` to `APIClient` and `SendSMSRequest` to support sending transactional push notifications.
4
+
5
+ ## Customerio 5.3.0 - December 8, 2023
6
+ ### Changed
7
+ - The `identify` method has been updated to allow the customer ID to be specified separately from the attributes, using the `customer_id` attribute. This allows a person to be updated by identifying them by e.g.: their email address. Thanks to trwalzer, jrbeck and jeremyw for the original changes that this is based on.
8
+ - It is no longer possible to set the `customer_id` attribute on a person. This is a side-effect of the changes to the `identify` method.
9
+
1
10
  ## Customerio 5.2.0 - December 8, 2023
2
11
  ### Changed
3
12
  - 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.
data/README.md CHANGED
@@ -1,16 +1,15 @@
1
- <p align="center">
1
+ <p align=center>
2
2
  <a href="https://customer.io">
3
- <img src="https://files.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LSFjPaMQn1zKdYh6i89%2F-LU6OglGKqQfqMd5Zl-V%2F-LU6OzOLnOvy8VLwfgdg%2FLogo-Color-Horizontal.png?alt=media&token=add29dd0-cabb-4440-b46b-aed21350ae90" height="60">
3
+ <img src="https://avatars.githubusercontent.com/u/1152079?s=200&v=4" height="60">
4
4
  </a>
5
- <p align="center">Power automated communication that people like to receive.</p>
6
5
  </p>
7
6
 
8
7
  [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blueviolet?logo=gitpod)](https://gitpod.io/#https://github.com/customerio/customerio-ruby/)
9
8
  [![ci](https://github.com/customerio/customerio-ruby/actions/workflows/main.yml/badge.svg)](https://github.com/customerio/customerio-ruby/actions/workflows/main.yml)
10
9
 
11
- # Customer.io Ruby
10
+ # Customer.io Ruby
12
11
 
13
- A ruby client for the [Customer.io Track API](https://customer.io/docs/api/#tag/trackOverview).
12
+ A ruby client for the [Customer.io Journeys Track API](https://customer.io/docs/api/track/).
14
13
 
15
14
  ## Installation
16
15
 
@@ -95,7 +94,7 @@ $customerio.identify(
95
94
  )
96
95
  ```
97
96
 
98
- ### Updating customers
97
+ ### Updating customers: Changing identifiers
99
98
 
100
99
  You can use the identify operation to update customers.
101
100
  If you need to change the `id` or `email` identifiers for a customer,
@@ -113,6 +112,35 @@ $customerio.identify(
113
112
  )
114
113
  ```
115
114
 
115
+ This method requires either the `id` or `cio_id` for the person. It does not work with email addresses.
116
+
117
+ You can also use this method to make other updates to the person using the `cio_id`.
118
+
119
+ ### Updating customers: Using email address
120
+
121
+ If you need to identify a person using their email address, then you can do so
122
+ by passing in a customer ID to the `identify` method. This allows you to specify
123
+ a customer ID that is different than the one used in the `id` attribute. E.g.:
124
+
125
+ ```ruby
126
+ # Arguments
127
+ # customer_id (required) - the customer ID to use for this customer, may be an id, email address, or the cio_id.
128
+ # This will be used to construct the URL but not sent in the body attributes.
129
+ # attributes (required) - a hash of information about the customer. You can pass any
130
+ # information that would be useful in your triggers. You
131
+ # must at least pass in an id, email, and created_at timestamp.
132
+
133
+ $customerio.identify(
134
+ :customer_id => "bob@example.com",
135
+ :location => "Australia"
136
+ )
137
+ ```
138
+
139
+ Note:
140
+
141
+ * If you want to use the `cio_id` in the `customer_id` field of `identify_customer_id`, you will need to prefix it with `"cio_"`. E.g.: `"cio_f000000d"` for a `cio_id` of `f000000d`.
142
+ * The `identify` method can identify the person using one of `customer_id`, `cio_id` or `id`. The order of precedence is `customer_id` > `cio_id` > `id`.
143
+
116
144
  ### Deleting customers
117
145
 
118
146
  Deleting a customer will remove them, and all their information from
data/customerio.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.email = ["john@customer.io"]
7
7
  gem.description = "A ruby client for the Customer.io event API."
8
8
  gem.summary = "A ruby client for the Customer.io event API."
9
- gem.homepage = "http://customer.io"
9
+ gem.homepage = "https://customer.io"
10
10
  gem.license = "MIT"
11
11
 
12
12
  gem.files = `git ls-files`.split($\)
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.add_dependency('multi_json', "~> 1.0")
20
20
  gem.add_dependency('addressable', '~> 2.8.0')
21
+ gem.add_dependency('base64', '~> 0.3.0')
21
22
 
22
23
  gem.add_development_dependency('rake', '~> 10.5')
23
24
  gem.add_development_dependency('rspec', '~> 3.10')
@@ -41,6 +41,21 @@ module Customerio
41
41
  end
42
42
  end
43
43
 
44
+ def send_sms(req)
45
+ raise "request must be an instance of Customerio::SendSMSRequest" unless req.is_a?(Customerio::SendSMSRequest)
46
+ response = @client.request(:post, send_sms_path, req.message)
47
+
48
+ case response
49
+ when Net::HTTPSuccess then
50
+ JSON.parse(response.body)
51
+ when Net::HTTPBadRequest then
52
+ json = JSON.parse(response.body)
53
+ raise Customerio::InvalidResponse.new(response.code, json['meta']['error'], response)
54
+ else
55
+ raise InvalidResponse.new(response.code, response.body)
56
+ end
57
+ end
58
+
44
59
  private
45
60
 
46
61
  def send_email_path
@@ -50,5 +65,9 @@ module Customerio
50
65
  def send_push_path
51
66
  "/v1/send/push"
52
67
  end
68
+
69
+ def send_sms_path
70
+ "/v1/send/sms"
71
+ end
53
72
  end
54
73
  end
@@ -151,16 +151,33 @@ module Customerio
151
151
 
152
152
  def create_or_update(attributes = {})
153
153
  attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
154
- if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id])
154
+ if is_empty?(attributes[:id]) && is_empty?(attributes[:cio_id]) && is_empty?(attributes[:customer_id])
155
155
  raise MissingIdAttributeError.new("Must provide a customer id")
156
156
  end
157
157
 
158
158
  # Use cio_id as the identifier, if present,
159
159
  # to allow the id and email identifiers to be updated.
160
+ # The person is identified by a customer ID, which is included
161
+ # in the path to the Track v1 API. Choose the ID in this order
162
+ # from highest to lowest precedence:
163
+ #
164
+ # 1. customer_id: "id", an email address, or "cio_id" value.
165
+ # Any "cio_id" values need to be prefixed "cio_"
166
+ # so that the Track v1 API knows it's a cio_id.
167
+ #
168
+ # 2. cio_id: The cio_id value (no prefix required).
169
+ #
170
+ # 3. id: The id value.
160
171
  customer_id = attributes[:id]
161
172
  if !is_empty?(attributes[:cio_id])
162
173
  customer_id = "cio_" + attributes[:cio_id]
163
174
  end
175
+ if !is_empty?(attributes[:customer_id])
176
+ customer_id = attributes[:customer_id]
177
+ end
178
+ # customer_id is not an attribute, so remove it.
179
+ attributes.delete(:customer_id)
180
+
164
181
  url = customer_path(customer_id)
165
182
  @client.request_and_verify_response(:put, url, attributes)
166
183
  end
@@ -0,0 +1,42 @@
1
+ require 'base64'
2
+
3
+ module Customerio
4
+ class SendSMSRequest
5
+ attr_reader :message
6
+
7
+ def initialize(opts)
8
+ @message = opts.delete_if { |field| invalid_field?(field) }
9
+ @message[:attachments] = {}
10
+ @message[:headers] = {}
11
+ end
12
+
13
+ def attach(name, data, encode: true)
14
+ raise "attachment #{name} already exists" if @message[:attachments].has_key?(name)
15
+ @message[:attachments][name] = encode ? Base64.strict_encode64(data) : data
16
+ end
17
+
18
+ private
19
+
20
+ REQUIRED_FIELDS = %i(identifiers transactional_message_id)
21
+
22
+ OPTIONAL_FIELDS = %i(
23
+ message_data
24
+ from
25
+ to
26
+ disable_message_retention
27
+ send_to_unsubscribed
28
+ tracked
29
+ queue_draft
30
+ send_at
31
+ language
32
+ )
33
+
34
+ def invalid_field?(field)
35
+ !REQUIRED_FIELDS.include?(field) && !OPTIONAL_FIELDS.include?(field)
36
+ end
37
+
38
+ def encode(data)
39
+ Base64.strict_encode64(data)
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module Customerio
2
- VERSION = "5.2.0"
2
+ VERSION = "5.4.0"
3
3
  end
data/lib/customerio.rb CHANGED
@@ -6,6 +6,7 @@ module Customerio
6
6
  require "customerio/client"
7
7
  require "customerio/requests/send_email_request"
8
8
  require "customerio/requests/send_push_request"
9
+ require "customerio/requests/send_sms_request"
9
10
  require "customerio/api"
10
11
  require "customerio/param_encoder"
11
12
  end
@@ -252,4 +252,63 @@ describe Customerio::APIClient do
252
252
  client.send_push(req).should eq({ "delivery_id" => 2 })
253
253
  end
254
254
  end
255
+
256
+ describe "#send_sms" do
257
+ it "sends a POST request to the /api/send/sms path" do
258
+ req = Customerio::SendSMSRequest.new(
259
+ identifiers: {
260
+ id: 'c1',
261
+ },
262
+ transactional_message_id: 1,
263
+ )
264
+
265
+ stub_request(:post, api_uri('/v1/send/sms'))
266
+ .with(headers: request_headers, body: req.message)
267
+ .to_return(status: 200, body: { delivery_id: 1 }.to_json, headers: {})
268
+
269
+ client.send_sms(req).should eq({ "delivery_id" => 1 })
270
+ end
271
+
272
+ it "handles validation failures (400)" do
273
+ req = Customerio::SendSMSRequest.new(
274
+ identifiers: {
275
+ id: 'c1',
276
+ },
277
+ transactional_message_id: 1,
278
+ )
279
+
280
+ err_json = { meta: { error: "example error" } }.to_json
281
+
282
+ stub_request(:post, api_uri('/v1/send/sms'))
283
+ .with(headers: request_headers, body: req.message)
284
+ .to_return(status: 400, body: err_json, headers: {})
285
+
286
+ lambda { client.send_sms(req) }.should(
287
+ raise_error(Customerio::InvalidResponse) { |error|
288
+ error.message.should eq "example error"
289
+ error.code.should eq "400"
290
+ }
291
+ )
292
+ end
293
+
294
+ it "handles other failures (5xx)" do
295
+ req = Customerio::SendSMSRequest.new(
296
+ identifiers: {
297
+ id: 'c1',
298
+ },
299
+ transactional_message_id: 1,
300
+ )
301
+
302
+ stub_request(:post, api_uri('/v1/send/sms'))
303
+ .with(headers: request_headers, body: req.message)
304
+ .to_return(status: 500, body: "Server unavailable", headers: {})
305
+
306
+ lambda { client.send_sms(req) }.should(
307
+ raise_error(Customerio::InvalidResponse) { |error|
308
+ error.message.should eq "Server unavailable"
309
+ error.code.should eq "500"
310
+ }
311
+ )
312
+ end
313
+ end
255
314
  end
data/spec/client_spec.rb CHANGED
@@ -173,6 +173,7 @@ describe Customerio::Client 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
175
  lambda { client.identify(cio_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
176
+ lambda { client.identify(customer_id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
176
177
  end
177
178
 
178
179
  it 'should not raise errors when attribute keys are strings' do
@@ -223,6 +224,39 @@ describe Customerio::Client do
223
224
  location: "here"
224
225
  })
225
226
  end
227
+
228
+ it "uses provided id rather than id" do
229
+ stub_request(:put, api_uri('/api/v1/customers/1234')).
230
+ with(body: json(id: "5")).
231
+ to_return(status: 200, body: "", headers: {})
232
+
233
+ client.identify(
234
+ customer_id: "1234",
235
+ id: "5"
236
+ )
237
+ end
238
+
239
+ it "uses provided cio_id rather than id" do
240
+ stub_request(:put, api_uri('/api/v1/customers/cio_5')).
241
+ with(body: json(id: "5")).
242
+ to_return(status: 200, body: "", headers: {})
243
+
244
+ client.identify(
245
+ customer_id: "cio_5",
246
+ id: "5"
247
+ )
248
+ end
249
+
250
+ it "uses provided email rather than id" do
251
+ stub_request(:put, api_uri('/api/v1/customers/customer@example.com')).
252
+ with(body: json(id: "5")).
253
+ to_return(status: 200, body: "", headers: {})
254
+
255
+ client.identify(
256
+ customer_id: "customer@example.com",
257
+ id: "5"
258
+ )
259
+ end
226
260
  end
227
261
 
228
262
  describe "#delete" do
@@ -650,7 +684,7 @@ describe Customerio::Client do
650
684
  }.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
651
685
  end
652
686
  end
653
-
687
+
654
688
  describe "#merge_customers" do
655
689
  before(:each) do
656
690
  @client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
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.2.0
4
+ version: 5.4.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-12-08 00:00:00.000000000 Z
11
+ date: 2025-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.8.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: base64
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -118,16 +132,17 @@ files:
118
132
  - lib/customerio/regions.rb
119
133
  - lib/customerio/requests/send_email_request.rb
120
134
  - lib/customerio/requests/send_push_request.rb
135
+ - lib/customerio/requests/send_sms_request.rb
121
136
  - lib/customerio/version.rb
122
137
  - spec/api_client_spec.rb
123
138
  - spec/base_client_spec.rb
124
139
  - spec/client_spec.rb
125
140
  - spec/spec_helper.rb
126
- homepage: http://customer.io
141
+ homepage: https://customer.io
127
142
  licenses:
128
143
  - MIT
129
144
  metadata: {}
130
- post_install_message:
145
+ post_install_message:
131
146
  rdoc_options: []
132
147
  require_paths:
133
148
  - lib
@@ -142,8 +157,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
157
  - !ruby/object:Gem::Version
143
158
  version: '0'
144
159
  requirements: []
145
- rubygems_version: 3.2.33
146
- signing_key:
160
+ rubygems_version: 3.0.3.1
161
+ signing_key:
147
162
  specification_version: 4
148
163
  summary: A ruby client for the Customer.io event API.
149
164
  test_files: