Class: Sentiero::Analytics::PageReportAnalyzer

Inherits:
Analyzer
  • Object
show all
Defined in:
lib/sentiero/analytics/page_report_analyzer.rb

Overview

Per-URL drill-down: composes the suite's metrics (heatmap, scroll, forms, vitals, frustration, errors, custom tags) for one URL into one report via ONE bounded Store#each_session_events scan. Per-segment math lives in shared Collectors::. Frustration is the exception: only detection is shared (FrustrationAnalyzer.detect_frustration_events); the cross-session aggregation differs, so this URL's attribution uses FrustrationCollector.

Constant Summary collapse

MAX_SELECTORS =

Output bounds — each caps a collector (flips #capped on hit).

200
MAX_SAMPLES_PER_METRIC =
2000
MAX_ERROR_GROUPS =
200
MAX_ERROR_OCCURRENCES =
50
MAX_CUSTOM_TAGS =
200
MAX_FIELDS =
500
TOP_ELEMENTS_LIMIT =

Display limits.

20
TOP_SELECTORS_LIMIT =
10

Constants included from Events

Events::CUSTOM, Events::INCREMENTAL, Events::META, Events::SOURCE_INPUT, Events::SOURCE_MOUSE_INTERACTION, Events::SOURCE_SCROLL

Instance Attribute Summary

Attributes inherited from Analyzer

#store

Instance Method Summary collapse

Methods inherited from Analyzer

#initialize

Methods included from EntryAttribution

#earlier?, #first_meta_href, #same_origin?, #update_entry_candidate

Methods included from Bounded

#bounded_fetch, #bounded_increment

Methods included from Stats

#mean, #offset_ms, #percentile, #top_counts

Constructor Details

This class inherits a constructor from Sentiero::Analytics::Analyzer

Instance Method Details

#analyze(target_url, limit: nil, since: nil, until_time: nil) ⇒ Object

since/until_time are epoch seconds. Every result key is always present.



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
# File 'lib/sentiero/analytics/page_report_analyzer.rb', line 35

def analyze(target_url, limit: nil, since: nil, until_time: nil)
  acc = new_accumulator

  _scanned, hit_cap = scan_sessions(limit: limit, since: since, until_time: until_time) do |summary, window_id, events|
    session_id = summary[:session_id]

    # Detect over the FULL window: frustration semantics span page
    # boundaries. FrustrationCollector then attributes each incident to a
    # segment by object identity.
    frustration = FrustrationAnalyzer.detect_frustration_events(events)

    segment_index = 0
    last_index = nil
    first_was_target = false
    target_segments = 0

    each_page_segment(events) do |url, segment, anchor|
      matches = url == target_url
      first_was_target = true if segment_index.zero? && matches
      last_index = segment_index if matches
      segment_index += 1

      next unless matches

      target_segments += 1
      acc[:page_views] += 1
      acc[:sessions][session_id] = true

      collect_time_on_page(acc, segment)
      collect_heatmap(acc, segment, session_id, window_id)
      acc[:vitals].collect(segment, session_id: session_id, window_id: window_id, anchor: anchor)
      acc[:errors].collect(segment, session_id: session_id, window_id: window_id, anchor: anchor)
      acc[:custom_tags].collect(segment)
      acc[:forms].collect(session_id, url, segment)
      acc[:scroll].observe(target_url, segment)
      acc[:frustration].collect(frustration, segment)
    end

    # entry/exit/bounce decided once per window from the segment order.
    if target_segments.positive?
      acc[:windows_on_page] += 1
      acc[:entries] += 1 if first_was_target
      acc[:exits] += 1 if last_index == segment_index - 1
      acc[:bounces] += 1 if segment_index == 1 && first_was_target
    end

    # One scroll sample per (session, window): deepest wins.
    acc[:scroll].flush_window
  end

  build_result(target_url, acc, hit_cap)
end