Class: Testimonials::PromptEvent

Inherits:
ApplicationRecord show all
Defined in:
app/models/testimonials/prompt_event.rb

Overview

The throttling ledger. Every auto-open is a "shown", every close without submitting is a "dismissed", every saved submission is a "submitted" — keyed by author_id for signed-in users, by a visitor cookie otherwise. eligible? reads this history so the widget never nags:

* submitted a testimonial     -> never auto-prompted for one again
* submitted NPS               -> not again within nps_reprompt_after
* shown or dismissed recently -> not again within reprompt_after
* shown max_prompts times     -> never auto-prompted for that kind again

Explicit opens (the user clicked something) bypass all of this.

Constant Summary collapse

KINDS =
%w[testimonial nps].freeze
ACTIONS =
%w[shown dismissed submitted].freeze

Class Method Summary collapse

Class Method Details

.eligible?(kind:, author_id: nil, visitor_token: nil, tenant: nil) ⇒ Boolean

Throttling is per-tenant: a user prompted in one tenant is still eligible in another, so each collection can ask independently.

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/models/testimonials/prompt_event.rb', line 32

def eligible?(kind:, author_id: nil, visitor_token: nil, tenant: nil)
  kind = kind.to_s
  return false unless KINDS.include?(kind)
  # No identity, no history: a brand-new visitor is always eligible.
  return true if author_id.blank? && visitor_token.blank?

  history = subject(author_id, visitor_token, tenant).where(kind: kind)
  config = Testimonials.config

  return false if (history, kind, config)
  return false if history.where(action: %w[shown dismissed])
                         .exists?(created_at: (Time.current - config.reprompt_after)..)

  history.where(action: 'shown').count < config.max_prompts
end

.record!(kind:, action:, author_id: nil, visitor_token: nil, tenant: nil) ⇒ Object



23
24
25
26
27
28
# File 'app/models/testimonials/prompt_event.rb', line 23

def record!(kind:, action:, author_id: nil, visitor_token: nil, tenant: nil)
  return if author_id.blank? && visitor_token.blank?

  create!(kind: kind.to_s, action: action.to_s, tenant: tenant.presence,
          author_id: author_id.presence, visitor_token: visitor_token.presence)
end