diff --git a/app/assets/javascripts/initializers/initializeBaseTracking.js.erb b/app/assets/javascripts/initializers/initializeBaseTracking.js.erb index b281ebe62..154a472ea 100644 --- a/app/assets/javascripts/initializers/initializeBaseTracking.js.erb +++ b/app/assets/javascripts/initializers/initializeBaseTracking.js.erb @@ -79,38 +79,61 @@ function logImpressions() { function trackCustomImpressions() { setTimeout(function(){ - var stickyNav = document.getElementById('article-show-primary-sticky-nav'); - var sidebarHTMLVariant = document.getElementById('html-variant-article-show-sidebar'); var ArticleElement = document.getElementById('article-body'); var tokenMeta = document.querySelector("meta[name='csrf-token']") - var randomNumber = Math.floor(Math.random() * 10); // 1 in 10; Only track 1 in 10 impressions var isBot = /bot|google|baidu|bing|msn|duckduckbot|teoma|slurp|yandex/i.test(navigator.userAgent) // is crawler - if (sidebarHTMLVariant && ArticleElement && tokenMeta && !isBot) { + var windowBigEnough = window.innerWidth > 1250 + + // Sidebar HTML variant tracking + var stickyNav = document.getElementById('article-show-primary-sticky-nav'); + var sidebarHTMLVariant = document.getElementById('html-variant-article-show-sidebar'); + if (sidebarHTMLVariant && ArticleElement && tokenMeta && !isBot && windowBigEnough) { var dataBody = { html_variant_id: sidebarHTMLVariant.dataset.variantId, article_id: ArticleElement.dataset.articleId, }; var csrfToken = tokenMeta.getAttribute('content'); - if (randomNumber === 1) { - window.fetch('/html_variant_trials', { - method: 'POST', - headers: { - 'X-CSRF-Token': csrfToken, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(dataBody), - credentials: 'same-origin', - }); - } + trackHTMLVariantTrial(dataBody, csrfToken) var successLinks = stickyNav.querySelectorAll('a,button'); //track all links and button clicks within nav for(var i = 0; i < successLinks.length; i++) { successLinks[i].addEventListener('click', function() { trackHtmlVariantSuccess(dataBody, csrfToken) }); } } + + // Below article HTML variant tracking + var belowArticleHTMLVariant = document.getElementById('html-variant-article-show-below-article'); + if (belowArticleHTMLVariant && ArticleElement && tokenMeta && !isBot && windowBigEnough) { + var dataBody = { + html_variant_id: belowArticleHTMLVariant.dataset.variantId, + article_id: ArticleElement.dataset.articleId, + }; + var csrfToken = tokenMeta.getAttribute('content'); + trackHTMLVariantTrial(dataBody, csrfToken) + var successLinks = belowArticleHTMLVariant.querySelectorAll('a,button'); //track all links and button clicks within nav + for(var i = 0; i < successLinks.length; i++) + { + successLinks[i].addEventListener('click', function() { trackHtmlVariantSuccess(dataBody, csrfToken) }); + } + } }, 1500) } +function trackHTMLVariantTrial(dataBody, csrfToken) { + var randomNumber = Math.floor(Math.random() * 10); // 1 in 10; Only track 1 in 10 impressions + if (randomNumber === 1) { + window.fetch('/html_variant_trials', { + method: 'POST', + headers: { + 'X-CSRF-Token': csrfToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(dataBody), + credentials: 'same-origin', + }); + } +} + function trackHtmlVariantSuccess(dataBody, csrfToken) { window.fetch('/html_variant_successes', { method: 'POST', diff --git a/app/assets/stylesheets/article-show.scss b/app/assets/stylesheets/article-show.scss index 027f2dd8d..b0ab97f28 100644 --- a/app/assets/stylesheets/article-show.scss +++ b/app/assets/stylesheets/article-show.scss @@ -918,6 +918,13 @@ article{ } } + .html-variant-wrapper { + width: 88%; + margin: 0px auto 25px; + @media screen and ( min-width: 500px ){ + width: 82%; + } + } } .dev-ios-native-body { @@ -955,41 +962,6 @@ article{ border-top: 27px solid $green; } } -.showpage-signin-cta{ - background: lighten($light-gray, 1%); - border: 1px solid darken($light-medium-gray, 15%); - box-shadow: $bold-shadow; - width: 680px; - max-width:82%; - margin: auto; - text-align: center; - padding: 40px 5%; - font-size: 1.1em; - line-height: 1.33em; - margin-bottom: 30px; - border-radius: 3px; - position: relative; - a{ - color: $black; - text-decoration: underline; - display: inline-block; - &.primary-cta-link{ - font-size: calc(1.3em + 0.2vw); - background: $bold-blue; - border-radius: 100px; - text-decoration: none; - padding: 16px 0px; - color: white; - width: 300px; - } - } - .showpage-signin-cta-subtext { - font-family: $monospace; - font-size:calc(0.62em + 0.13vw); - color: lighten($medium-gray, 10%); - font-weight: bold; - } -} .show-comments-header{ width:800px; diff --git a/app/controllers/html_variants_controller.rb b/app/controllers/html_variants_controller.rb index 01806bd23..220c32e04 100644 --- a/app/controllers/html_variants_controller.rb +++ b/app/controllers/html_variants_controller.rb @@ -4,11 +4,11 @@ class HtmlVariantsController < ApplicationController def index authorize HtmlVariant @html_variants = if params[:state] == "mine" - current_user.html_variants.order("created_at DESC").includes(:user) + current_user.html_variants.order("created_at DESC").includes(:user).page(params[:page]).per(15) elsif params[:state] == "admin" - HtmlVariant.where(published: true).order("created_at DESC").includes(:user) + HtmlVariant.where(published: true, approved: false).order("created_at DESC").includes(:user).page(params[:page]).per(15) else - HtmlVariant.where(published: true, approved: true).order("success_rate DESC").includes(:user) + HtmlVariant.where(published: true, approved: true).order("success_rate DESC").includes(:user).page(params[:page]).per(15) end end @@ -38,7 +38,6 @@ class HtmlVariantsController < ApplicationController def create authorize HtmlVariant @html_variant = HtmlVariant.new(html_variant_params) - @html_variant.group = "article_show_sidebar_cta" @html_variant.user_id = current_user.id if @html_variant.save flash[:success] = "HTML Variant Created" diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb index 210c2093c..f13038c9f 100644 --- a/app/controllers/stories_controller.rb +++ b/app/controllers/stories_controller.rb @@ -205,6 +205,7 @@ class StoriesController < ApplicationController def handle_article_show @article_show = true + @variant_number = params[:variant_version] || rand(2) @comment = Comment.new assign_user_and_org @comments_to_show_count = @article.cached_tag_list_array.include?("discuss") ? 50 : 30 diff --git a/app/models/html_variant.rb b/app/models/html_variant.rb index 791252287..7d98329ed 100644 --- a/app/models/html_variant.rb +++ b/app/models/html_variant.rb @@ -1,7 +1,7 @@ class HtmlVariant < ApplicationRecord validates :html, presence: true validates :name, uniqueness: true - validates :group, inclusion: { in: %w(article_show_sidebar_cta) } + validates :group, inclusion: { in: %w(article_show_sidebar_cta article_show_below_article_cta) } validates :success_rate, presence: true validate :no_edits belongs_to :user, optional: true @@ -14,27 +14,27 @@ class HtmlVariant < ApplicationRecord save! end - def self.find_for_test(tags = []) + def self.find_for_test(tags = [], group = "article_show_sidebar_cta") tags_array = tags + ["", nil] if rand(10) == 1 # 10% return completely random - find_random_for_test(tags_array) + find_random_for_test(tags_array, group) else # 90% chance return one in top 10 - find_top_for_test(tags_array) + find_top_for_test(tags_array, group) end end - def self.find_top_for_test(tags_array) - where(group: "article_show_sidebar_cta", approved: true, published: true, target_tag: tags_array).order("success_rate DESC").limit(rand(1..15)).sample + def self.find_top_for_test(tags_array, group) + where(group: group, approved: true, published: true, target_tag: tags_array).order("success_rate DESC").limit(rand(1..15)).sample end - def self.find_random_for_test(tags_array) - where(group: "article_show_sidebar_cta", approved: true, published: true, target_tag: tags_array).order("RANDOM()").first + def self.find_random_for_test(tags_array, group) + where(group: group, approved: true, published: true, target_tag: tags_array).order("RANDOM()").first end private def no_edits - if (approved && html_changed? || name_changed? || group_changed?) && persisted? + if (approved && (html_changed? || name_changed? || group_changed?)) && persisted? errors.add(:base, "cannot change once published and approved") end end diff --git a/app/policies/html_variant_policy.rb b/app/policies/html_variant_policy.rb index d7d705087..dc7935d66 100644 --- a/app/policies/html_variant_policy.rb +++ b/app/policies/html_variant_policy.rb @@ -1,33 +1,33 @@ class HtmlVariantPolicy < ApplicationPolicy def index? - user_admin? + minimal_admin? end def show? - user_admin? + minimal_admin? end def edit? - user_admin? + minimal_admin? end def update? - user_admin? + minimal_admin? end def new? - user_admin? + minimal_admin? end def create? - user_admin? + minimal_admin? end def destroy? - user_admin? + minimal_admin? end def permitted_attributes - %i[html name published approved target_tag] + %i[html name published approved target_tag group] end end diff --git a/app/views/articles/_actions.html.erb b/app/views/articles/_actions.html.erb index d0b250a45..d5ed7ea5f 100644 --- a/app/views/articles/_actions.html.erb +++ b/app/views/articles/_actions.html.erb @@ -40,11 +40,13 @@ -<% unless user_signed_in? %> -