amplitude-api 0.1.1 → 0.3.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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AmplitudeAPI
2
4
  # AmplitudeAPI::Identification
3
5
  class Identification
@@ -16,7 +18,7 @@ class AmplitudeAPI
16
18
  # @param [ String ] user_id a user_id to associate with the identification
17
19
  # @param [ String ] device_id a device_id to associate with the identification
18
20
  # @param [ Hash ] user_properties various properties to attach to the user identification
19
- def initialize(user_id: '', device_id: nil, user_properties: {})
21
+ def initialize(user_id: "", device_id: nil, user_properties: {})
20
22
  self.user_id = user_id
21
23
  self.device_id = device_id if device_id
22
24
  self.user_properties = user_properties
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AmplitudeAPI
2
- VERSION = '0.1.1'.freeze
4
+ VERSION = "0.3.0"
3
5
  end
data/readme.md CHANGED
@@ -19,7 +19,7 @@ AmplitudeAPI.config.api_key = "abcdef123456"
19
19
 
20
20
 
21
21
  event = AmplitudeAPI::Event.new({
22
- user_id: "123",
22
+ user_id: "12345",
23
23
  event_type: "clicked on home",
24
24
  time: Time.now,
25
25
  insert_id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
@@ -42,12 +42,12 @@ AmplitudeAPI.config.api_key = "abcdef123456"
42
42
  # Configure your Amplitude Secret Key
43
43
  AmplitudeAPI.config.secret_key = "secretMcSecret"
44
44
 
45
- AmplitudeAPI.delete(user_ids: [233],
45
+ AmplitudeAPI.delete(user_ids: ["12345"],
46
46
  requester: "privacy@example.com"
47
47
  )
48
48
  ```
49
49
 
50
- Currently, we are using this in Rails and using ActiveJob to dispatch events asynchronously. I plan on moving
50
+ Currently, we are using this in Rails and using ActiveJob to dispatch events asynchronously. I plan on moving
51
51
  background/asynchronous support into this gem.
52
52
 
53
53
  ## What's Next
@@ -56,7 +56,7 @@ background/asynchronous support into this gem.
56
56
  * Configurable default account to use when no `user_id` present
57
57
 
58
58
  ## Other useful resources
59
- * [Amplitude HTTP Api Documentation](https://amplitude.zendesk.com/hc/en-us/articles/204771828)
59
+ * [Amplitude HTTP API V2 Api Documentation](https://developers.amplitude.com/docs/http-api-v2)
60
60
  * [Segment.io Amplitude integration](https://segment.com/docs/integrations/amplitude/)
61
61
 
62
62
  ## Contributing
@@ -1,277 +1,318 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe AmplitudeAPI::Event do
4
6
  user = Struct.new(:id)
5
7
 
6
- context 'with a user object' do
7
- describe '#body' do
8
+ context "with a user object" do
9
+ describe "#body" do
8
10
  it "populates with the user's id" do
9
11
  event = described_class.new(
10
12
  user_id: user.new(123),
11
- event_type: 'clicked on home'
13
+ event_type: "clicked on home"
12
14
  )
13
15
  expect(event.to_hash[:user_id]).to eq(123)
14
16
  end
15
17
  end
16
18
  end
17
19
 
18
- context 'with a user id' do
19
- describe '#body' do
20
+ context "with a user id" do
21
+ describe "#body" do
20
22
  it "populates with the user's id" do
21
23
  event = described_class.new(
22
24
  user_id: 123,
23
- event_type: 'clicked on home'
25
+ event_type: "clicked on home"
24
26
  )
25
27
  expect(event.to_hash[:user_id]).to eq(123)
26
28
  end
27
29
  end
28
30
  end
29
31
 
30
- context 'without a user' do
31
- describe '#body' do
32
- it 'populates with the unknown user' do
32
+ context "without a user" do
33
+ describe "#body" do
34
+ it "populates with the unknown user" do
33
35
  event = described_class.new(
34
36
  user_id: nil,
35
- event_type: 'clicked on home'
37
+ event_type: "clicked on home"
36
38
  )
37
39
  expect(event.to_hash[:user_id]).to eq(AmplitudeAPI::USER_WITH_NO_ACCOUNT)
38
40
  end
39
41
  end
40
42
  end
41
43
 
42
- describe 'init' do
43
- context 'attributes' do
44
- it 'accepts string attributes' do
44
+ describe "init" do
45
+ context "attributes" do
46
+ it "accepts string attributes" do
45
47
  time = Time.at(1_451_606_400_000 / 1_000)
46
48
  event = described_class.new(
47
- 'user_id' => 123,
48
- 'device_id' => 'abcd',
49
- 'event_type' => 'sausage',
50
- 'event_properties' => { 'a' => 'b' },
51
- 'user_properties' => { 'c' => 'd' },
52
- 'time' => time,
53
- 'ip' => '127.0.0.1',
54
- 'platform' => 'Web',
55
- 'country' => 'United States',
56
- 'insert_id' => 'bestId'
49
+ "user_id" => 123,
50
+ "device_id" => "abcd",
51
+ "event_type" => "sausage",
52
+ "event_properties" => { "a" => "b" },
53
+ "user_properties" => { "c" => "d" },
54
+ "time" => time,
55
+ "ip" => "127.0.0.1",
56
+ "platform" => "Web",
57
+ "country" => "United States",
58
+ "insert_id" => "bestId"
57
59
  )
58
60
 
59
- expect(event.to_hash).to eq(event_type: 'sausage',
61
+ expect(event.to_hash).to eq(event_type: "sausage",
60
62
  user_id: 123,
61
- device_id: 'abcd',
62
- event_properties: { 'a' => 'b' },
63
- user_properties: { 'c' => 'd' },
63
+ device_id: "abcd",
64
+ event_properties: { "a" => "b" },
65
+ user_properties: { "c" => "d" },
64
66
  time: 1_451_606_400_000,
65
- ip: '127.0.0.1',
66
- platform: 'Web',
67
- country: 'United States',
68
- insert_id: 'bestId')
67
+ ip: "127.0.0.1",
68
+ platform: "Web",
69
+ country: "United States",
70
+ insert_id: "bestId")
69
71
  end
70
72
 
71
- it 'accepts symbol attributes' do
73
+ it "accepts symbol attributes" do
72
74
  time = Time.at(1_451_606_400_000 / 1_000)
73
75
  event = described_class.new(
74
76
  user_id: 123,
75
- device_id: 'abcd',
76
- event_type: 'sausage',
77
- event_properties: { 'a' => 'b' },
78
- user_properties: { 'c' => 'd' },
77
+ device_id: "abcd",
78
+ event_type: "sausage",
79
+ event_properties: { "a" => "b" },
80
+ user_properties: { "c" => "d" },
79
81
  time: time,
80
- ip: '127.0.0.1',
81
- platform: 'Web',
82
- country: 'United States',
83
- insert_id: 'bestId'
82
+ ip: "127.0.0.1",
83
+ platform: "Web",
84
+ country: "United States",
85
+ insert_id: "bestId"
84
86
  )
85
87
 
86
- expect(event.to_hash).to eq(event_type: 'sausage',
88
+ expect(event.to_hash).to eq(event_type: "sausage",
87
89
  user_id: 123,
88
- device_id: 'abcd',
89
- event_properties: { 'a' => 'b' },
90
- user_properties: { 'c' => 'd' },
90
+ device_id: "abcd",
91
+ event_properties: { "a" => "b" },
92
+ user_properties: { "c" => "d" },
91
93
  time: 1_451_606_400_000,
92
- ip: '127.0.0.1',
93
- platform: 'Web',
94
- country: 'United States',
95
- insert_id: 'bestId')
94
+ ip: "127.0.0.1",
95
+ platform: "Web",
96
+ country: "United States",
97
+ insert_id: "bestId")
96
98
  end
97
99
  end
98
100
 
99
- context 'the user does not send in a price' do
100
- it 'raises an error if the user sends in a product_id' do
101
+ context "the user sends a revenue_type or a product_id" do
102
+ it "raises an error if there is not a price neither a revenue" do
101
103
  expect do
102
104
  described_class.new(
103
105
  user_id: 123,
104
- event_type: 'bad event',
105
- product_id: 'hopscotch.4lyfe'
106
+ event_type: "bad event",
107
+ product_id: "hopscotch.4lyfe"
106
108
  )
107
- end.to raise_error(ArgumentError)
109
+ end.to raise_error ArgumentError, /You must provide a price or a revenue/
110
+
111
+ expect do
112
+ described_class.new(
113
+ user_id: 123,
114
+ event_type: "bad event",
115
+ revenue_type: "whatever"
116
+ )
117
+ end.to raise_error ArgumentError, /You must provide a price or a revenue/
108
118
  end
109
119
 
110
- it 'raises an error if the user sends in a revenue_type' do
120
+ it "does not raise an error if there is a price" do
111
121
  expect do
112
122
  described_class.new(
113
123
  user_id: 123,
114
- event_type: 'bad event',
115
- revenue_type: 'tax return'
124
+ event_type: "bad event",
125
+ product_id: "hopscotch.4lyfe",
126
+ price: 10.2
116
127
  )
117
- end.to raise_error(ArgumentError)
128
+ end.not_to raise_error
129
+
130
+ expect do
131
+ described_class.new(
132
+ user_id: 123,
133
+ event_type: "bad event",
134
+ revenue_type: "whatever",
135
+ price: 10.2
136
+ )
137
+ end.not_to raise_error
138
+ end
139
+
140
+ it "does not raise an error if there is a revenue" do
141
+ expect do
142
+ described_class.new(
143
+ user_id: 123,
144
+ event_type: "bad event",
145
+ product_id: "hopscotch.4lyfe",
146
+ revenue: 100.1
147
+ )
148
+ end.not_to raise_error
149
+
150
+ expect do
151
+ described_class.new(
152
+ user_id: 123,
153
+ event_type: "bad event",
154
+ revenue_type: "whatever",
155
+ revenue: 100.1
156
+ )
157
+ end.not_to raise_error
118
158
  end
119
159
  end
120
160
  end
121
161
 
122
- describe '#to_hash' do
123
- it 'includes the event type' do
162
+ describe "#to_hash" do
163
+ it "includes the event type" do
124
164
  event = described_class.new(
125
165
  user_id: 123,
126
- event_type: 'clicked on home'
166
+ event_type: "clicked on home"
127
167
  )
128
- expect(event.to_hash[:event_type]).to eq('clicked on home')
168
+ expect(event.to_hash[:event_type]).to eq("clicked on home")
129
169
  end
130
170
 
131
- it 'includes arbitrary properties' do
171
+ it "includes arbitrary properties" do
132
172
  event = described_class.new(
133
173
  user_id: 123,
134
- event_type: 'clicked on home',
174
+ event_type: "clicked on home",
135
175
  event_properties: { abc: :def }
136
176
  )
137
177
  expect(event.to_hash[:event_properties]).to eq(abc: :def)
138
178
  end
139
179
 
140
- describe 'time' do
141
- it 'includes a time for the event' do
180
+ describe "time" do
181
+ it "includes a time for the event" do
142
182
  time = Time.at(1_451_606_400_000 / 1_000)
143
183
  event = described_class.new(
144
184
  user_id: 123,
145
- event_type: 'clicked on home',
185
+ event_type: "clicked on home",
146
186
  time: time
147
187
  )
148
188
  expect(event.to_hash[:time]).to eq(1_451_606_400_000)
149
189
  end
150
190
 
151
- it 'does not include time if it is not set' do
191
+ it "does not include time if it is not set" do
152
192
  event = described_class.new(
153
193
  user_id: 123,
154
- event_type: 'clicked on home'
194
+ event_type: "clicked on home"
155
195
  )
156
196
  expect(event.to_hash).not_to have_key(:time)
157
197
  end
158
198
  end
159
199
 
160
- describe 'insert_id' do
161
- it 'includes an insert_id for the event' do
200
+ describe "insert_id" do
201
+ it "includes an insert_id for the event" do
162
202
  event = described_class.new(
163
203
  user_id: 123,
164
- event_type: 'clicked on home',
165
- insert_id: 'foo-bar'
204
+ event_type: "clicked on home",
205
+ insert_id: "foo-bar"
166
206
  )
167
- expect(event.to_hash[:insert_id]).to eq('foo-bar')
207
+ expect(event.to_hash[:insert_id]).to eq("foo-bar")
168
208
  end
169
209
 
170
- it 'does not include insert_id if it is not set' do
210
+ it "does not include insert_id if it is not set" do
171
211
  event = described_class.new(
172
212
  user_id: 123,
173
- event_type: 'clicked on home'
213
+ event_type: "clicked on home"
174
214
  )
175
215
  expect(event.to_hash).not_to have_key(:insert_id)
176
216
  end
177
217
  end
178
218
 
179
- describe 'platform' do
180
- it 'includes the platform for the event' do
219
+ describe "platform" do
220
+ it "includes the platform for the event" do
181
221
  event = described_class.new(
182
222
  user_id: 123,
183
- event_type: 'clicked on home',
184
- platform: 'Web'
223
+ event_type: "clicked on home",
224
+ platform: "Web"
185
225
  )
186
- expect(event.to_hash[:platform]).to eq('Web')
226
+ expect(event.to_hash[:platform]).to eq("Web")
187
227
  end
188
228
 
189
- it 'does not include the platform if it is not set' do
229
+ it "does not include the platform if it is not set" do
190
230
  event = described_class.new(
191
231
  user_id: 123,
192
- event_type: 'clicked on home'
232
+ event_type: "clicked on home"
193
233
  )
194
234
  expect(event.to_hash).not_to have_key(:platform)
195
235
  end
196
236
  end
197
237
 
198
- describe 'country' do
199
- it 'includes the country for the event' do
238
+ describe "country" do
239
+ it "includes the country for the event" do
200
240
  event = described_class.new(
201
241
  user_id: 123,
202
- event_type: 'clicked on home',
203
- country: 'United States'
242
+ event_type: "clicked on home",
243
+ country: "United States"
204
244
  )
205
- expect(event.to_hash[:country]).to eq('United States')
245
+ expect(event.to_hash[:country]).to eq("United States")
206
246
  end
207
247
 
208
- it 'does not include the country if it is not set' do
248
+ it "does not include the country if it is not set" do
209
249
  event = described_class.new(
210
250
  user_id: 123,
211
- event_type: 'clicked on home'
251
+ event_type: "clicked on home"
212
252
  )
213
253
  expect(event.to_hash).not_to have_key(:country)
214
254
  end
215
255
  end
216
256
 
217
- describe 'revenue params' do
218
- it 'includes the price if it is set' do
257
+ describe "revenue params" do
258
+ it "includes the price if it is set" do
219
259
  price = 100_000.99
220
260
  event = described_class.new(
221
261
  user_id: 123,
222
- event_type: 'clicked on home',
262
+ event_type: "clicked on home",
223
263
  price: price
224
264
  )
225
265
  expect(event.to_hash[:price]).to eq(price)
226
266
  end
227
267
 
228
- it 'sets the quantity to 1 if the price is set and the quantity is not' do
229
- price = 100_000.99
268
+ it "includes the quantity if it is set" do
269
+ quantity = 100
230
270
  event = described_class.new(
231
271
  user_id: 123,
232
- event_type: 'clicked on home',
233
- price: price
272
+ event_type: "clicked on home",
273
+ quantity: quantity,
274
+ price: 10.99
234
275
  )
235
- expect(event.to_hash[:quantity]).to eq(1)
276
+ expect(event.to_hash[:quantity]).to eq(quantity)
236
277
  end
237
278
 
238
- it 'includes the quantity if it is set' do
239
- quantity = 100
279
+ it "includes the revenue if it is set" do
280
+ revenue = 100
240
281
  event = described_class.new(
241
282
  user_id: 123,
242
- event_type: 'clicked on home',
243
- quantity: quantity,
244
- price: 10.99
283
+ event_type: "clicked on home",
284
+ quantity: 456,
285
+ revenue: revenue
245
286
  )
246
- expect(event.to_hash[:quantity]).to eq(quantity)
287
+ expect(event.to_hash[:revenue]).to eq(revenue)
247
288
  end
248
289
 
249
- it 'includes the productID if set' do
250
- product_id = 'hopscotch.subscriptions.rule'
290
+ it "includes the productID if set" do
291
+ product_id = "hopscotch.subscriptions.rule"
251
292
  event = described_class.new(
252
293
  user_id: 123,
253
- event_type: 'clicked on home',
294
+ event_type: "clicked on home",
254
295
  price: 199.99,
255
296
  product_id: product_id
256
297
  )
257
298
  expect(event.to_hash[:productId]).to eq(product_id)
258
299
  end
259
300
 
260
- it 'includes the revenueType if set' do
261
- revenue_type = 'income'
301
+ it "includes the revenueType if set" do
302
+ revenue_type = "income"
262
303
  event = described_class.new(
263
304
  user_id: 123,
264
- event_type: 'clicked on home',
305
+ event_type: "clicked on home",
265
306
  price: 199.99,
266
307
  revenue_type: revenue_type
267
308
  )
268
309
  expect(event.to_hash[:revenueType]).to eq(revenue_type)
269
310
  end
270
311
 
271
- it 'does not include revenue params if they are not set' do
312
+ it "does not include revenue params if they are not set" do
272
313
  event = described_class.new(
273
314
  user_id: 123,
274
- event_type: 'clicked on home'
315
+ event_type: "clicked on home"
275
316
  )
276
317
  expect(event.to_hash).not_to have_key(:quantity)
277
318
  expect(event.to_hash).not_to have_key(:revenueType)
@@ -280,4 +321,44 @@ describe AmplitudeAPI::Event do
280
321
  end
281
322
  end
282
323
  end
324
+
325
+ describe "arbitrary properties" do
326
+ # We need to create a class for each test because the methods we are calling
327
+ # in this test group are modifying the class
328
+ let(:klass) { Class.new described_class }
329
+
330
+ let(:event) {
331
+ klass.new(
332
+ user_id: 123,
333
+ event_type: "bad event"
334
+ )
335
+ }
336
+
337
+ it "creates arbitrary properties when assigning values" do
338
+ event.arbitrary_property = "arbitrary value"
339
+
340
+ expect(event.arbitrary_property).to eq "arbitrary value"
341
+ end
342
+
343
+ it "responds_to? arbitrary properties" do
344
+ event.arbitrary_property = "arbitrary value"
345
+
346
+ expect(event.respond_to?(:arbitrary_property)).to be true
347
+ expect(event.respond_to?(:arbitrary_property=)).to be true
348
+ end
349
+
350
+ it "do not accepts blocks when assigning values to create properties" do
351
+ expect do
352
+ event.arbitrary_property { puts "whatever" }
353
+ end.to raise_error NoMethodError
354
+ end
355
+
356
+ it "includes arbitrary properties in the generated hash" do
357
+ event.arbitrary_property = "arbitrary value"
358
+
359
+ hash = event.to_hash
360
+
361
+ expect(hash).to include(arbitrary_property: "arbitrary value")
362
+ end
363
+ end
283
364
  end