Module: Consently::TagsHelper
- Defined in:
- app/helpers/consently/tags_helper.rb
Overview
The three helpers a host application calls: the tags in
, the noscript fallbacks right after , and the banner anywhere on the page.Instance Method Summary collapse
-
#consently_banner(policy_url: nil) ⇒ Object
The banner, the preferences panel, and the JavaScript that releases the blocked tags.
- #consently_consent ⇒ Object
-
#consently_data_layer_push(event, category: :analytics, **payload) ⇒ Object
Push an event onto the dataLayer from a view, respecting consent: with no analytics consent the event is simply not emitted.
-
#consently_ecommerce(event, items: [], category: :analytics, **params) ⇒ Object
A GA4 ecommerce event in the shape Google expects, from whatever your models happen to look like:.
-
#consently_embed(kind, identifier, category: :marketing, title: nil, ratio: "16 / 9", **iframe_options) ⇒ Object
An embedded video or map that waits for consent.
-
#consently_log_url ⇒ Object
Where the banner POSTs the decision, when consent logging is on and the engine is mounted.
-
#consently_noscript_tags ⇒ Object
Goes directly after
- Google Tag Manager and Meta both still ship a noscript fallback. -
#consently_policy ⇒ Object
A complete cookie policy for the tags this request would load: every category, every vendor, every cookie it sets and for how long, plus whether the visitor has agreed to it right now.
-
#consently_preferences_link(name = nil, **options, &block) ⇒ Object
A "Cookie settings" link for the footer.
-
#consently_stylesheet_tag ⇒ Object
The banner brings its own plain CSS - no framework, no build step.
-
#consently_tags ⇒ Object
Every tag configured for this request.
Instance Method Details
#consently_banner(policy_url: nil) ⇒ Object
The banner, the preferences panel, and the JavaScript that releases the blocked tags. Render it once per page, ideally at the end of the body.
The container stays in the DOM after a choice is made so that
consently_preferences_link has something to reopen.
43 44 45 46 47 48 49 50 |
# File 'app/helpers/consently/tags_helper.rb', line 43 def (policy_url: nil) return "".html_safe unless && Consently.(request) render "consently/banner", consent: , policy_url: policy_url || , categories: Consently.config.optional_categories end |
#consently_consent ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'app/helpers/consently/tags_helper.rb', line 65 def @consently_consent ||= if Consently.(request) Consent.( [Consently.config.], version: Consently.config., max_age: Consently.config. ) else # Nobody to ask, so nothing is held back. Consent.new(categories: Consently.config.categories, version: Consently.config.) end end |
#consently_data_layer_push(event, category: :analytics, **payload) ⇒ Object
Push an event onto the dataLayer from a view, respecting consent: with no analytics consent the event is simply not emitted.
<%= consently_data_layer_push("newsletter_signup", source: "footer") %>
82 83 84 85 86 87 |
# File 'app/helpers/consently/tags_helper.rb', line 82 def (event, category: :analytics, **payload) return "".html_safe unless && .granted?(category) payload = payload.merge(event: event) "window.dataLayer = window.dataLayer || []; window.dataLayer.push(#{payload.to_json});" end |
#consently_ecommerce(event, items: [], category: :analytics, **params) ⇒ Object
A GA4 ecommerce event in the shape Google expects, from whatever your models happen to look like:
<%= consently_ecommerce("purchase", items: @order.line_items,
value: @order.total, currency: "EUR", transaction_id: @order.number) %>
Items may be hashes already in GA4 shape, or any object answering to a few obvious names (id/sku, name, price, quantity, category, brand, variant) - a LineItem or a Product usually does.
The previous ecommerce object is cleared first, as Google asks, so two events on one page cannot bleed into each other.
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'app/helpers/consently/tags_helper.rb', line 101 def (event, items: [], category: :analytics, **params) return "".html_safe unless && .granted?(category) ecommerce = params.merge(items: Array(items).map { |item| (item) }) payload = { event: event, ecommerce: ecommerce.compact } <<~JS.strip window.dataLayer = window.dataLayer || []; window.dataLayer.push({ ecommerce: null }); window.dataLayer.push(#{payload.to_json}); JS end |
#consently_embed(kind, identifier, category: :marketing, title: nil, ratio: "16 / 9", **iframe_options) ⇒ Object
An embedded video or map that waits for consent. Blocking scripts is only half the job: a YouTube iframe sets cookies all by itself.
<%= consently_embed :youtube, "dQw4w9WgXcQ" %>
<%= consently_embed :vimeo, "76979871", category: :analytics %>
<%= consently_embed :google_maps, "Bahnhofstrasse 12, Berlin" %>
<%= consently_embed :custom, "https://example.com/widget", title: "Widget" %>
Until the category is granted the visitor sees a placeholder with a button that opens the preferences panel; the iframe appears the moment they agree, without a reload.
134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'app/helpers/consently/tags_helper.rb', line 134 def (kind, identifier, category: :marketing, title: nil, ratio: "16 / 9", **) src = (kind, identifier) return "".html_safe if src.blank? render "consently/embed", src: src, title: title || t("consently.embed.title_#{kind}", default: t("consently.embed.title_default")), category: category.to_sym, ratio: ratio, granted: .granted?(category), iframe_options: end |
#consently_log_url ⇒ Object
Where the banner POSTs the decision, when consent logging is on and the engine is mounted. Nil otherwise, and the banner skips the request.
156 157 158 159 160 161 162 |
# File 'app/helpers/consently/tags_helper.rb', line 156 def return nil unless Consently.config. . rescue NoMethodError, NameError nil end |
#consently_noscript_tags ⇒ Object
Goes directly after
- Google Tag Manager and Meta both still ship a noscript fallback. Only rendered for categories already granted: there is no way to hold an iframe back and release it later.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'app/helpers/consently/tags_helper.rb', line 25 def return "".html_safe unless fallbacks = Consently.(request).filter_map do |provider| next unless .granted?(provider.category) provider.noscript&.html_safe end return "".html_safe if fallbacks.empty? content_tag(:noscript, safe_join(fallbacks, "\n")) end |
#consently_policy ⇒ Object
A complete cookie policy for the tags this request would load: every category, every vendor, every cookie it sets and for how long, plus whether the visitor has agreed to it right now.
Drop it into your own policy page under your own heading and legal text.
119 120 121 |
# File 'app/helpers/consently/tags_helper.rb', line 119 def render "consently/policy", tags: Consently.(request), consent: end |
#consently_preferences_link(name = nil, **options, &block) ⇒ Object
A "Cookie settings" link for the footer. Reopens the panel.
Marked rather than wired: the link lives outside the banner element, so a data-action on it would never bind. The controller watches the whole document for a click on anything carrying this attribute, which also means your own markup can reopen the panel just by wearing it.
58 59 60 61 62 63 |
# File 'app/helpers/consently/tags_helper.rb', line 58 def (name = nil, **, &block) name ||= t("consently.preferences_link") [:data] = { consently_open: true }.merge([:data] || {}) link_to(name, "#consently", , &block) end |
#consently_stylesheet_tag ⇒ Object
The banner brings its own plain CSS - no framework, no build step. The
look is driven by custom properties, so overriding a few variables is
usually enough; rails g consently:views is there for the rest.
150 151 152 |
# File 'app/helpers/consently/tags_helper.rb', line 150 def stylesheet_link_tag "consently", media: "all" end |
#consently_tags ⇒ Object
Every tag configured for this request. Tags whose category the visitor has not agreed to are rendered inert (type="text/plain") and the banner turns them into real scripts the moment consent is given - so a visitor who accepts does not have to reload to be counted.
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'app/helpers/consently/tags_helper.rb', line 9 def return "".html_safe unless parts = [] parts << if Consently.config.stylesheet parts << if Consently.config. Consently.(request).each do |provider| provider.scripts.each { |script| parts << (script, provider, (provider)) } end safe_join(parts, "\n") end |