Class: Sentiero::Analytics::FormCollector
- Inherits:
-
Object
- Object
- Sentiero::Analytics::FormCollector
- Defined in:
- lib/sentiero/analytics/collectors/form_collector.rb
Overview
Per-URL form interaction math. The single definition of what an "input" and a "submit" are in rrweb terms. Two completion semantics for two callers:
#completed_count — sessions with inputs where EVERY input segment was
submitted (strict; one abandoned segment disqualifies).
#submitted_count — sessions with ANY __form_submit event, regardless of
input timing.
Constant Summary collapse
- SUBMIT_TAG =
Recorder tag for a document-level form submit.
"__form_submit"- DROP_OFF_LIMIT =
Output cap for the drop-off table.
50
Constants included from Events
Events::CUSTOM, Events::INCREMENTAL, Events::META, Events::SOURCE_INPUT, Events::SOURCE_MOUSE_INTERACTION, Events::SOURCE_SCROLL
Instance Attribute Summary collapse
-
#capped ⇒ Object
readonly
Returns the value of attribute capped.
-
#total_submits ⇒ Object
readonly
Returns the value of attribute total_submits.
Instance Method Summary collapse
-
#collect(session_id, url, segment, labels: {}) ⇒ Object
Returns the count of input events found.
-
#completed_count ⇒ Object
Sessions with inputs where NO input segment was abandoned; a submit on a later page never masks an abandonment.
-
#initialize(max_fields: nil) ⇒ FormCollector
constructor
max_fields: nil unbounded; an Integer caps the fields hash, flipping #capped.
- #started_count ⇒ Object
-
#submitted_count ⇒ Object
Counts a submit on the target URL even when inputs landed on a prior segment.
- #summarize_drop_off(include_labels: false) ⇒ Object
- #summarize_fields(started, include_labels: false) ⇒ Object
Methods included from Bounded
#bounded_fetch, #bounded_increment
Constructor Details
#initialize(max_fields: nil) ⇒ FormCollector
max_fields: nil unbounded; an Integer caps the fields hash, flipping #capped.
27 28 29 30 31 32 33 34 35 36 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 27 def initialize(max_fields: nil) @max_fields = max_fields @total_submits = 0 @fields = {} # [url, node_id] => field-stats hash @drop_off = Hash.new(0) # [url, node_id] => abandon count @started = {} # session_id => true (≥1 input event seen) @submitted = {} # session_id => true (≥1 submit event, any segment) @abandoned = {} # session_id => true (≥1 input segment not submitted) @capped = false end |
Instance Attribute Details
#capped ⇒ Object (readonly)
Returns the value of attribute capped.
24 25 26 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 24 def capped @capped end |
#total_submits ⇒ Object (readonly)
Returns the value of attribute total_submits.
24 25 26 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 24 def total_submits @total_submits end |
Instance Method Details
#collect(session_id, url, segment, labels: {}) ⇒ Object
Returns the count of input events found. labels: => label from the segment's DOM snapshot; {} omits them.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 40 def collect(session_id, url, segment, labels: {}) @total_submits += segment.count { |e| submit?(e) } @submitted[session_id] = true if segment.any? { |e| submit?(e) } inputs = segment.select { |e| input?(e) } return 0 if inputs.empty? @started[session_id] = true record_fields(session_id, url, inputs, labels) first_input_at = inputs.first["timestamp"] unless segment_submitted?(segment, first_input_at) @abandoned[session_id] = true @drop_off[[url, node_id(inputs.last)]] += 1 end inputs.size end |
#completed_count ⇒ Object
Sessions with inputs where NO input segment was abandoned; a submit on a later page never masks an abandonment.
70 71 72 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 70 def completed_count @started.count { |id, _| !@abandoned.key?(id) } end |
#started_count ⇒ Object
59 60 61 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 59 def started_count @started.size end |
#submitted_count ⇒ Object
Counts a submit on the target URL even when inputs landed on a prior segment.
64 65 66 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 64 def submitted_count @submitted.size end |
#summarize_drop_off(include_labels: false) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 90 def summarize_drop_off(include_labels: false) @drop_off .sort_by { |(url, id), count| [-count, url.to_s, id] } .first(DROP_OFF_LIMIT) .map do |(url, id), count| row = {} row[:field_id] = id row[:label] = @fields.key?([url, id]) ? @fields[[url, id]][:label] : nil if include_labels row[:url] = url row[:count] = count row end end |
#summarize_fields(started, include_labels: false) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/sentiero/analytics/collectors/form_collector.rb', line 74 def summarize_fields(started, include_labels: false) @fields .sort_by { |(url, id), stats| [-stats[:sessions], url.to_s, id] } .map do |(url, id), stats| row = {} row[:field_id] = id row[:label] = stats[:label] if include_labels row[:url] = url row[:sessions] = stats[:sessions] row[:completion_rate] = started.zero? ? 0.0 : stats[:sessions].to_f / started row[:avg_time_to_fill_ms] = stats[:units].zero? ? 0.0 : stats[:total_fill_ms] / stats[:units] row[:total_refills] = stats[:total_refills] row end end |