File: subject.rb

package info (click to toggle)
ruby-snowplow-tracker 0.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 176 kB
  • sloc: ruby: 515; makefile: 4
file content (360 lines) | stat: -rw-r--r-- 14,801 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# Copyright (c) 2013-2021 Snowplow Analytics Ltd. All rights reserved.
#
# This program is licensed to you under the Apache License Version 2.0,
# and you may not use this file except in compliance with the Apache License Version 2.0.
# You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the Apache License Version 2.0 is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.

# Author:: Snowplow Analytics Ltd
# Copyright:: Copyright (c) 2013-2021 Snowplow Analytics Ltd
# License:: Apache License Version 2.0


module SnowplowTracker
  # Subject objects store information about the user associated with the event,
  # such as their `user_id`, what type of device they used, or what size screen
  # that device had. Also, they store which platform the event occurred on -
  # e.g. server-side app, mobile, games console, etc.
  #
  # Subject parameters are saved into the tracked event as part of the 'atomic'
  # event properties, which have their own column in the eventual table of
  # events. For example, a Subject's `user_id` parameter will be sent as `uid`
  # in the raw event payload, ending up in the `user_id` column. These
  # parameters represent part of the [Snowplow Tracker
  # Protocol](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol),
  # which defines a Snowplow event.
  #
  # Each {Tracker} is initialized with a Subject. This means that every event by
  # default has the platform (`p` parameter in the raw event) `srv`: server-side
  # app. Platform is the only preset Subject parameter, which can be overriden
  # using the {#set_platform} method. All other parameters must be set manually.
  # This can be done directly on the Subject, or, if it is associated with a
  # Tracker, via the Tracker, which has access to all the methods of its
  # Subject.
  #
  # Your server-side code may not have access to all these parameters, or they
  # might not be useful to you. All the Subject parameters are optional, except
  # `platform`.
  #
  # @example Subject methods can be called from their associated Tracker
  #   # Creating the components explicitly
  #   emitter = SnowplowTracker::Emitter.new(endpoint: 'localhost')
  #   subject = SnowplowTracker::Subject.new
  #   tracker = SnowplowTracker::Tracker.new(emitters: emitter, subject: subject)
  #
  #   # These lines are equivalent
  #   subject.set_user_id('12345')
  #   tracker.set_user_id('12345')
  #
  #   # This would also be equivalent
  #   emitter = SnowplowTracker::Emitter.new(endpoint: 'localhost')
  #   subject = SnowplowTracker::Subject.new
  #   subject.set_user_id('12345')
  #   tracker = SnowplowTracker::Tracker.new(emitters: emitter, subject: subject)
  #
  # @example Adding properties to the auto-generated Tracker-associated Subject
  #   # Creating the components
  #   emitter = SnowplowTracker::Emitter.new(endpoint: 'localhost')
  #   tracker = SnowplowTracker::Tracker.new(emitters: emitter)
  #
  #   # Set Subject parameters via the Tracker
  #   tracker.set_user_id('12345')
  #
  # Since many of the Subject parameters describe the user, different Subject
  # properties may often be desired for each event, if there are multiple users.
  # This can be achieved in one of three ways:
  #
  # 1. the properties of the Tracker-associated Subject can be overriden by the
  #    properties of an event-specific Subject. A Subject can be added to any
  #    Tracker `#track_x_event` method call, as one of the arguments. Remember to
  #    set the platform for the event Subject if you're not using `srv`.
  # 2. the Tracker-associated Subject can be swapped for another Subject, using
  #    the Tracker method {Tracker#set_subject}.
  # 3. the properties of the Tracker-associated Subject can be changed before
  #    every `#track_x_event`, by calling the Subject methods via the Tracker.
  #
  # @see Tracker#set_subject
  # @see
  #   https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol
  #   the Snowplow Tracker Protocol
  # @see
  #   https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/ruby-tracker/enriching-your-events/
  #   the Snowplow docs page about adding context and other extra data to events
  # @api public
  #
  # @note All the Subject instance methods return the Subject object, allowing
  #   method chaining, e.g.
  #   `SnowplowTracker::Subject.new.set_timezone('Europe/London').set_user_id('12345')`
  class Subject
    # @private
    DEFAULT_PLATFORM = 'srv'

    # @api public
    #
    # | `p` value | Platform |
    # | ---- | ---- |
    # | app | General App |
    # | cnsl | Games Console |
    # | iot | Internet of Things |
    # | mob | Mobile/Tablet |
    # | pc | Desktop/Laptop/Netbook |
    # | srv [DEFAULT] | Server-side App |
    # | tv | Connected TV |
    # | web | Web (including Mobile Web) |
    SUPPORTED_PLATFORMS = %w[app cnsl iot mob pc srv tv web]

    # Access the Subject parameters
    # @example
    #   SnowplowTracker::Subject.new.set_user_id('12345').details
    #   => {"p"=>"srv", "uid"=>"12345"}
    # @api public
    attr_reader :details

    # @api public
    def initialize
      @details = { 'p' => DEFAULT_PLATFORM }
    end

    # Set the platform to one of the supported platform values.
    # @note Value is sent in the event as `p` (raw event) or `platform` (processed event).
    # @see Subject::SUPPORTED_PLATFORMS
    # @param [String] platform a valid platform choice
    # @example
    #   subject.set_platform('app')
    # @return self
    # @api public
    def set_platform(platform)
      raise "#{platform} is not a supported platform" unless SUPPORTED_PLATFORMS.include?(platform)

      @details['p'] = platform
      self
    end

    # Set the unique business-defined user ID for a user.
    # @note Value is sent in the event as `uid` (raw event) or `user_id` (processed event).
    # For example, an email address.
    # @example Example user IDs
    #   # an email address
    #   janet.bloggs@email.com
    #
    #   # a username
    #   janetabloggs2021
    #
    # @param [String] user_id a unique user ID
    # @return self
    # @api public
    def set_user_id(user_id)
      @details['uid'] = user_id
      self
    end

    # Set a business-defined fingerprint for a user.
    # @note Value is sent in the event as `fp` (raw event) or `user_fingerprint` (processed event).
    # @param [Num] fingerprint a user fingerprint
    # @return self
    # @example
    #   subject.set_fingerprint(4048966212)
    # @api public
    def set_fingerprint(fingerprint)
      @details['fp'] = fingerprint
      self
    end

    # Set the device screen resolution.
    # @note Value is sent in the event as `res` (raw event) or `dvce_screenheight` and `dvce_screenwidth` (processed event).
    # @param [Integer] width the screen width, in pixels (must be a positive integer)
    # @param [Integer] height the screen height, in pixels (must be a positive integer)
    # @return self
    # @example
    #   subject.set_screen_resolution(width: 2880, height: 1800)
    # @api public
    def set_screen_resolution(width:, height:)
      @details['res'] = "#{width}x#{height}"
      self
    end

    # Set the dimensions of the current viewport.
    # @note Value is sent in the event as `vp` (raw event) or `br_viewwidth` and `br_viewheight` (processed event).
    # @param [Integer] width the viewport width, in pixels (must be a positive integer)
    # @param [Integer] height the viewport height, in pixels (must be a positive integer)
    # @return self
    # @example
    #   subject.set_viewport(width: 1440, height: 762)
    # @api public
    def set_viewport(width:, height:)
      @details['vp'] = "#{width}x#{height}"
      self
    end

    # Set the color depth of the browser, in bits per pixel.
    # @note Value is sent in the event as `cd` (raw event) or `br_colordepth` (processed event).
    # @param [Num] depth the colour depth
    # @example
    #   subject.set_color_depth(24)
    # @return self
    # @api public
    def set_color_depth(depth)
      @details['cd'] = depth
      self
    end

    # Set the timezone to that of the user's OS.
    # @note Value is sent in the event as `tz` (raw event) or `os_timezone` (processed event).
    # @example
    #   subject.set_timezone('Africa/Lagos')
    # @param [String] timezone the timezone
    # @return self
    # @api public
    def set_timezone(timezone)
      @details['tz'] = timezone
      self
    end

    # Set the language.
    # @note Value is sent in the event as `lang` (raw event) or `br_lang` (processed event).
    # @example Setting the language to Spanish
    #   subject.set_lang('es')
    # @param [String] lang the language being used on the device
    # @return self
    # @api public
    def set_lang(lang)
      @details['lang'] = lang
      self
    end

    # Set the domain user ID.
    # @note Value is sent in the event as `duid` (raw event) or `domain_userid` (processed event).
    # @see Subject#set_network_user_id
    # @see Subject#set_domain_session_id
    # @see Subject#set_domain_session_idx
    # @see https://github.com/simplybusiness/snowplow_ruby_duid/ snowplow_ruby_duid, a third party gem
    # @see https://github.com/snowplow-incubator/snowplow-ruby-tracker-examples
    #   Ruby tracker example Rails app
    # @example
    #   subject.set_domain_user_id('aeb1691c5a0ee5a6')
    # @param [String] duid the unique domain user ID
    # @return self
    # @api public
    #
    # The `domain_userid` is a client-side unique user ID, which is set by the
    # browser-based JavaScript tracker, and stored in a first party cookie
    # (cookie name: `_sp_id`). For stitching together client-side and
    # server-side events originating from the same user, the domain user ID can
    # be extracted from the cookie and set using this method. A third party gem,
    # [snowplow_ruby_duid](https://github.com/simplybusiness/snowplow_ruby_duid/),
    # has been created to help with this.
    #
    # @example Ruby on Rails: getting the domain_user_id from the cookie
    #   # Assuming the Snowplow JavaScript has also been incorporated
    #   # cookies are accessible only within a Controller
    #   def snowplow_domain_userid
    #     sp_cookie = cookies.find { |key, _value| key =~ /^_sp_id/ }
    #     sp_cookie.last.split(".").first if sp_cookie.present?
    #   end
    #
    def set_domain_user_id(duid)
      @details['duid'] = duid
      self
    end

    # Set the domain session ID.
    # @note Value is sent in the event as `sid` (raw event) or `domain_sessionid` (processed event).
    # @see Subject#set_network_user_id
    # @see Subject#set_domain_user_id
    # @see Subject#set_domain_session_idx
    # @example
    #   subject.set_domain_session_id('9c65e7f3-8e8e-470d-b243-910b5b300da0')
    # @param [String] sid the unique domain session ID
    # @return self
    # @api public
    #
    # The `domain_sessionid` is a client-side unique ID for a user's current
    # session. It is set by the browser-based JavaScript trackers, and stored in
    # a first party cookie (cookie name: `_sp_id`), along with other parameters
    # such as `domain_userid`. For stitching together client-side and
    # server-side events originating from the same user and session, the domain
    # session ID can be extracted from the cookie and set using this method.
    def set_domain_session_id(sid)
      @details['sid'] = sid
      self
    end

    # Set the domain session index.
    # @note Value is sent in the event as `vid` (raw event) or `domain_sessionidx` (processed event).
    # @see Subject#set_network_user_id
    # @see Subject#set_domain_user_id
    # @see Subject#set_domain_session_id
    # @example
    #   subject.set_domain_session_idx(3)
    # @param [Num] vid the number of sessions
    # @return self
    # @api public
    #
    # The `domain_sessionidx` is a client-side property that records how many
    # visits (unique `domain_sessionid`s) a user (a unique `domain_userid`) has
    # made to the site. It is stored in the first party cookie set by the
    # JavaScript tracker, along with other parameters such as `domain_userid`.
    # For stitching together client-side and server-side events originating from
    # the same user and session, the domain session index can be extracted from
    # the cookie and set using this method.
    def set_domain_session_idx(vid)
      @details['vid'] = vid
      self
    end

    # Set the user's IP address.
    # @note Value is sent in the event as `ip` (raw event) or `user_ipaddress` (processed event).
    # @param [String] ip the IP address
    # @return self
    # @example
    #   subject.set_ip_address('37.157.33.178')
    # @api public
    def set_ip_address(ip)
      @details['ip'] = ip
      self
    end

    # Set the browser user agent.
    # @note Value is sent in the event as `ua` (raw event) or `useragent` (processed event).
    # @example
    #   subject.set_useragent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:92.0) Gecko/20100101 Firefox/92.0')
    # @param [String] useragent the user agent string
    # @return self
    # @api public
    def set_useragent(useragent)
      @details['ua'] = useragent
      self
    end

    # Set the network user ID.
    # @note Value is sent in the event as `tnuid` (raw event) and `network_userid` (processed event).
    # @see Subject#set_domain_user_id
    #
    # The network user ID is, like the `domain_userid`, a cookie-based unique
    # user ID. It is stored in a third party cookie set by the event collector,
    # hence the name "network" as it is set at a network level. It is the
    # server-side user identifier. The raw event does not contain a `nuid`
    # value; the `network_userid` property is added when the event is processed.
    #
    # The default behaviour is for the collector to provide a new cookie/network
    # user ID for each event it receives. This method provides the ability to
    # override the collector cookie's value with your own generated ID.
    #
    # Domain user IDs set on the Subject in this way are sent as `tnuid` in the
    # raw event.
    #
    # @example
    #   subject.set_network_user_id('ecdff4d0-9175-40ac-a8bb-325c49733607')
    # @param [String] nuid the network user ID
    # @return self
    # @api public
    def set_network_user_id(nuid)
      @details['tnuid'] = nuid
      self
    end
  end
end