From 255b7dc7a385e04183f552a36d2de5410f9975a0 Mon Sep 17 00:00:00 2001
From: Sanne de Vries
Date: Tue, 21 Jul 2026 14:01:39 +0200
Subject: [PATCH 1/2] Refine verification banner UI and copy
- Simplify failure CTAs: keep "Check again" as primary, add ghost
"Review installation" (or "Try another URL" when a custom URL retry
is offered); remove installation-guide, change-method, and view-snippet
expandable logic
- Render inline "verify your installation manually" / "review your
installation" links inside recommendation text (offer_custom_url_input
scenarios) via safe HTML helpers, avoiding HEEx whitespace pitfalls
- Tighten diagnostics title and body copy
- Move the "Setup pending" pill in the sites list to replace the
percentage indicator; use the generic pill component
- Extend the notice component with title_class override and a spinner
slot; swap success icon to solid check-circle
---
.../verification/diagnostics.ex | 46 ++-
extra/lib/plausible_web/live/verification.ex | 2 -
lib/plausible_web/components/generic.ex | 30 +-
.../live/components/verification_banner.ex | 293 +++++++++---------
lib/plausible_web/live/sites.ex | 14 +-
.../verification/checks_test.exs | 50 ++-
.../components/verification_banner_test.exs | 86 +++--
test/plausible_web/live/verification_test.exs | 16 +-
8 files changed, 300 insertions(+), 237 deletions(-)
diff --git a/extra/lib/plausible/installation_support/verification/diagnostics.ex b/extra/lib/plausible/installation_support/verification/diagnostics.ex
index 0773c07550f8..75d2d66cd9e6 100644
--- a/extra/lib/plausible/installation_support/verification/diagnostics.ex
+++ b/extra/lib/plausible/installation_support/verification/diagnostics.ex
@@ -59,7 +59,7 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_succeeds_only_after_cache_bust Error.new!(%{
message: "We detected an issue with your site's cache",
recommendation:
- "Please clear the cache for your site to ensure that your visitors will load the latest version of your site that has Plausible correctly installed",
+ "Clear the cache for your site to ensure your visitors load the latest version of your site with Plausible correctly installed",
url:
"https://plausible.io/docs/troubleshoot-integration#have-you-cleared-the-cache-of-your-site"
})
@@ -121,10 +121,9 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
end
@error_proxy_network_error Error.new!(%{
- message:
- "We got an unexpected response from the proxy you are using for Plausible",
+ message: "We couldn't verify your proxied installation",
recommendation:
- "Please check that you've configured the proxied /event route correctly",
+ "We received an unexpected response from your proxy. Check that you've configured the proxied /event route correctly",
url: "https://plausible.io/docs/proxy/introduction"
})
@error_plausible_network_error Error.new!(%{
@@ -174,9 +173,9 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_csp_disallowed Error.new!(%{
message:
- "We encountered an issue with your site's Content Security Policy (CSP)",
+ "Your site's Content Security Policy (CSP) is blocking Plausible",
recommendation:
- "Please add plausible.io domain specifically to the allowed list of domains in your site's CSP",
+ "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics",
url:
"https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
})
@@ -191,9 +190,9 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
do: handled_error(@error_csp_disallowed)
@error_domain_not_found Error.new!(%{
- message: "We couldn't find your website at <%= @attempted_url %>",
+ message: "We couldn't reach <%= @attempted_url %>",
recommendation:
- "Please check that the domain you entered is correct and reachable publicly. If it's intentionally private, you'll need to verify that Plausible works manually",
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
url: @verify_manually_url
})
@@ -207,10 +206,9 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
end
@error_browserless_network Error.new!(%{
- message:
- "We couldn't verify your website at <%= @attempted_url %>",
+ message: "We couldn't verify <%= @attempted_url %>",
recommendation:
- "Accessing the website resulted in a network error. Please verify your installation manually",
+ "We encountered a network error while trying to access your website. You can verify your installation manually or review your installation",
url: @verify_manually_url
})
@@ -228,8 +226,7 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
end
@error_browserless_temporary Error.new!(%{
- message:
- "Our verification tool encountered a temporary service error",
+ message: "Our verification service is temporarily unavailable",
recommendation:
"Please try again in a few minutes or verify your installation manually",
url: @verify_manually_url
@@ -241,10 +238,9 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
end
@error_unexpected_page_response Error.new!(%{
- message:
- "We couldn't verify your website at <%= @attempted_url %>",
+ message: "We couldn't verify <%= @attempted_url %>",
recommendation:
- "Accessing the website resulted in an unexpected status code <%= @page_response_status %>. Please check for anything that might be blocking us from reaching your site, like a firewall, authentication requirements, or CDN rules. If you'd prefer, you can skip this and verify your installation manually",
+ "Accessing your website returned an unexpected status code (<%= @page_response_status %>). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually or review your installation",
url: @verify_manually_url
})
@@ -290,25 +286,25 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_plausible_not_found_for_manual Error.new!(%{
message: @message_plausible_not_found,
recommendation:
- "Please make sure you've copied the snippet to the head of your site, or verify your installation manually",
+ "Make sure you've copied the snippet to the head of your site, or verify your installation manually",
url: @verify_manually_url
})
@error_plausible_not_found_for_npm Error.new!(%{
message: @message_plausible_not_found,
recommendation:
- "Please make sure you've initialized Plausible on your site, or verify your installation manually",
+ "Make sure you've initialized Plausible on your site, or verify your installation manually",
url: @verify_manually_url
})
@error_plausible_not_found_for_gtm Error.new!(%{
message: @message_plausible_not_found,
recommendation:
- "Please make sure you've configured the GTM template correctly, or verify your installation manually",
+ "Make sure you've configured the GTM template correctly, or verify your installation manually",
url: @verify_manually_url
})
@error_plausible_not_found_for_wordpress Error.new!(%{
message: @message_plausible_not_found,
recommendation:
- "Please make sure you've enabled the plugin, or verify your installation manually",
+ "Make sure you've enabled the WordPress plugin, or verify your installation manually",
url: @verify_manually_url
})
defp error_plausible_not_found(selected_installation_type) do
@@ -320,32 +316,32 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
end
end
- @unexpected_domain_message "Plausible test event is not for this site"
+ @unexpected_domain_message "Your Plausible snippet is configured for a different domain"
@error_unexpected_domain_for_manual Error.new!(%{
message: @unexpected_domain_message,
recommendation:
- "Please check that the snippet on your site matches the installation instructions exactly, or verify your installation manually",
+ "Check that the snippet on your site matches the one shown in the installation instructions, or verify your installation manually",
url: @verify_manually_url
})
@error_unexpected_domain_for_npm Error.new!(%{
message: @unexpected_domain_message,
recommendation:
- "Please check that you've initialized Plausible with the correct domain, or verify your installation manually",
+ "Check you've initialized Plausible with the correct domain, or verify your installation manually",
url: @verify_manually_url
})
@error_unexpected_domain_for_gtm Error.new!(%{
message: @unexpected_domain_message,
recommendation:
- "Please check that you've entered the ID in the GTM template correctly, or verify your installation manually",
+ "Check you've entered the ID in the GTM template correctly, or verify your installation manually",
url: @verify_manually_url
})
@error_unexpected_domain_for_wordpress Error.new!(%{
message: @unexpected_domain_message,
recommendation:
- "Please check that you've installed the WordPress plugin correctly, or verify your installation manually",
+ "Check you've installed the WordPress plugin correctly, or verify your installation manually",
url: @verify_manually_url
})
defp error_unexpected_domain(selected_installation_type) do
diff --git a/extra/lib/plausible_web/live/verification.ex b/extra/lib/plausible_web/live/verification.ex
index 57611d11f436..ff4742bf3a56 100644
--- a/extra/lib/plausible_web/live/verification.ex
+++ b/extra/lib/plausible_web/live/verification.ex
@@ -83,14 +83,12 @@ defmodule PlausibleWeb.Live.Verification do
~H"""
<.live_component
module={@component}
- installation_type={get_installation_type(@tracker_script_configuration)}
domain={@domain}
id="verification-standalone"
attempts={@attempts}
flow={@flow}
super_admin?={@super_admin?}
custom_url_input?={@custom_url_input?}
- tracker_script_configuration={@tracker_script_configuration}
dismissed?={@dismissed?}
/>
"""
diff --git a/lib/plausible_web/components/generic.ex b/lib/plausible_web/components/generic.ex
index 2dd458386723..173e6a6a6f88 100644
--- a/lib/plausible_web/components/generic.ex
+++ b/lib/plausible_web/components/generic.ex
@@ -12,25 +12,37 @@ defmodule PlausibleWeb.Components.Generic do
gray: %{
bg: "bg-gray-100 dark:bg-gray-800",
icon: "text-gray-600 dark:text-gray-300",
- title_text: "text-sm text-gray-900 dark:text-gray-100",
+ title_text: "text-gray-900 dark:text-gray-100",
body_text: "text-sm text-gray-800 dark:text-gray-200 leading-5"
},
+ indigo: %{
+ bg: "bg-indigo-100/60 dark:bg-indigo-900/40",
+ icon: "text-indigo-500",
+ title_text: "text-gray-900 dark:text-gray-100",
+ body_text: "text-sm text-gray-600 dark:text-gray-100/60 leading-5"
+ },
+ green: %{
+ bg: "bg-green-100/60 dark:bg-green-900/40",
+ icon: "text-green-500",
+ title_text: "text-gray-900 dark:text-gray-100",
+ body_text: "text-sm text-gray-600 dark:text-gray-100/60 leading-5"
+ },
yellow: %{
bg: "bg-yellow-100/60 dark:bg-yellow-900/40",
icon: "text-yellow-500",
- title_text: "text-sm text-gray-900 dark:text-gray-100",
+ title_text: "text-gray-900 dark:text-gray-100",
body_text: "text-sm text-gray-600 dark:text-gray-100/60 leading-5"
},
red: %{
bg: "bg-red-100 dark:bg-red-900/30",
icon: "text-red-600 dark:text-red-500",
- title_text: "text-sm text-gray-900 dark:text-gray-100",
+ title_text: "text-gray-900 dark:text-gray-100",
body_text: "text-sm text-gray-600 dark:text-gray-100/60 leading-5"
},
white: %{
bg: "bg-white dark:bg-gray-900 shadow-sm dark:shadow-none",
icon: "text-gray-600 dark:text-gray-400",
- title_text: "text-sm text-gray-900 dark:text-gray-100",
+ title_text: "text-gray-900 dark:text-gray-100",
body_text: "text-sm text-gray-600 dark:text-gray-300 leading-5"
}
}
@@ -222,6 +234,7 @@ defmodule PlausibleWeb.Components.Generic do
attr(:show_icon, :boolean, default: true)
attr(:class, :string, default: "")
attr(:icon_class, :string, default: "")
+ attr(:title_class, :string, default: "")
attr(:rest, :global)
slot(:inner_block)
slot(:actions)
@@ -253,7 +266,14 @@ defmodule PlausibleWeb.Components.Generic do
<% end %>
-
+
{@title}
diff --git a/lib/plausible_web/live/components/verification_banner.ex b/lib/plausible_web/live/components/verification_banner.ex
index eecca8992d88..12c355af2094 100644
--- a/lib/plausible_web/live/components/verification_banner.ex
+++ b/lib/plausible_web/live/components/verification_banner.ex
@@ -7,10 +7,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
use Plausible
alias PlausibleWeb.Router.Helpers, as: Routes
- alias PlausibleWeb.Components.Icons
- alias PlausibleWeb.Live.Installation.Instructions
alias Plausible.InstallationSupport.{State, Result}
- alias Plausible.Site.TrackerScriptConfiguration
import PlausibleWeb.Components.Generic
import PlausibleWeb.Live.Components.Form
@@ -35,9 +32,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
attr(:interpretation, Result, default: nil)
attr(:attempts, :integer, default: 0)
attr(:flow, :string, default: "")
- attr(:installation_type, :string, default: nil)
attr(:custom_url_input?, :boolean, default: false)
- attr(:tracker_script_configuration, TrackerScriptConfiguration, default: nil)
attr(:dismissed?, :boolean, default: false)
def render(assigns) do
@@ -62,11 +57,9 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
attempts={@attempts}
domain={@domain}
flow={@flow}
- installation_type={@installation_type}
super_admin?={@super_admin?}
verification_state={@verification_state}
custom_url_input?={@custom_url_input?}
- tracker_script_configuration={@tracker_script_configuration}
/>
"""
@@ -94,7 +87,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
-
- Setup pending
-
- <.site_stats sparkline={@sparkline} />
+ <.site_stats sparkline={@sparkline} needs_verification?={@needs_verification?} />
@@ -680,6 +674,7 @@ defmodule PlausibleWeb.Live.Sites do
end
attr(:sparkline, :any, required: true)
+ attr(:needs_verification?, :boolean, default: false)
def site_stats(assigns) do
~H"""
@@ -708,7 +703,10 @@ defmodule PlausibleWeb.Live.Sites do
- <.percentage_change change={@sparkline.visitors_change} />
+ <.pill :if={@needs_verification?} color={:yellow}>
+ Setup pending
+
+ <.percentage_change :if={not @needs_verification?} change={@sparkline.visitors_change} />
diff --git a/test/plausible/installation_support/verification/checks_test.exs b/test/plausible/installation_support/verification/checks_test.exs
index a0b7ef39a8dd..e53c569880fd 100644
--- a/test/plausible/installation_support/verification/checks_test.exs
+++ b/test/plausible/installation_support/verification/checks_test.exs
@@ -22,12 +22,12 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
ok?: false,
data: %{offer_custom_url_input: true},
errors: [
- ^any(:string, ~r/We couldn't find your website at #{@url_to_verify}$/)
+ ^any(:string, ~r/We couldn't reach #{@url_to_verify}$/)
],
recommendations: [
%{
text:
- "Please check that the domain you entered is correct and reachable publicly. If it's intentionally private, you'll need to verify that Plausible works manually",
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
url:
"https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
}
@@ -49,12 +49,12 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
ok?: false,
data: %{offer_custom_url_input: true},
errors: [
- ^any(:string, ~r/We couldn't find your website at #{url_to_verify}$/)
+ ^any(:string, ~r/We couldn't reach #{url_to_verify}$/)
],
recommendations: [
%{
text:
- "Please check that the domain you entered is correct and reachable publicly. If it's intentionally private, you'll need to verify that Plausible works manually",
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
url:
"https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
}
@@ -94,13 +94,13 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
for {installation_type, expected_recommendation} <- [
{"wordpress",
- "Please check that you've installed the WordPress plugin correctly, or verify your installation manually"},
+ "Check you've installed the WordPress plugin correctly, or verify your installation manually"},
{"gtm",
- "Please check that you've entered the ID in the GTM template correctly, or verify your installation manually"},
+ "Check you've entered the ID in the GTM template correctly, or verify your installation manually"},
{"npm",
- "Please check that you've initialized Plausible with the correct domain, or verify your installation manually"},
+ "Check you've initialized Plausible with the correct domain, or verify your installation manually"},
{"manual",
- "Please check that the snippet on your site matches the installation instructions exactly, or verify your installation manually"}
+ "Check that the snippet on your site matches the one shown in the installation instructions, or verify your installation manually"}
] do
test "returns error when test event domain doesn't match the expected domain, with recommendation for installation type: #{installation_type}" do
verification_stub =
@@ -119,7 +119,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
- errors: ["Plausible test event is not for this site"],
+ errors: ["Your Plausible snippet is configured for a different domain"],
recommendations: [
%{
text: unquote(expected_recommendation),
@@ -154,7 +154,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
- errors: [^any(:string, ~r/.*proxy.*/)],
+ errors: [^any(:string, ~r/.*proxied.*/)],
recommendations: [
%{
text: ^any(:string, ~r/.*proxied.*/),
@@ -213,7 +213,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "Please make sure you've copied the snippet to the head of your site, or verify your installation manually",
+ "Make sure you've copied the snippet to the head of your site, or verify your installation manually",
url:
"https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
}
@@ -236,12 +236,12 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
errors: [
- "We encountered an issue with your site's Content Security Policy (CSP)"
+ "Your site's Content Security Policy (CSP) is blocking Plausible"
],
recommendations: [
%{
text:
- "Please add plausible.io domain specifically to the allowed list of domains in your site's CSP",
+ "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics",
url:
"https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
}
@@ -261,13 +261,11 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
data: %{offer_custom_url_input: true},
- errors: [
- "We couldn't verify your website at https://example.com"
- ],
+ errors: ["We couldn't verify https://example.com"],
recommendations: [
%{
text:
- "Accessing the website resulted in a network error. Please verify your installation manually",
+ "We encountered a network error while trying to access your website. You can verify your installation manually or review your installation",
url:
"https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
}
@@ -291,13 +289,11 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
data: %{offer_custom_url_input: true},
- errors: [
- "We couldn't verify your website at https://example.com"
- ],
+ errors: ["We couldn't verify https://example.com"],
recommendations: [
%{
text:
- "Accessing the website resulted in an unexpected status code 403. Please check for anything that might be blocking us from reaching your site, like a firewall, authentication requirements, or CDN rules. If you'd prefer, you can skip this and verify your installation manually",
+ "Accessing your website returned an unexpected status code (403). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually or review your installation",
url:
"https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
}
@@ -309,13 +305,13 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
for {installation_type, expected_recommendation} <- [
{"wordpress",
- "Please make sure you've enabled the plugin, or verify your installation manually"},
+ "Make sure you've enabled the WordPress plugin, or verify your installation manually"},
{"gtm",
- "Please make sure you've configured the GTM template correctly, or verify your installation manually"},
+ "Make sure you've configured the GTM template correctly, or verify your installation manually"},
{"npm",
- "Please make sure you've initialized Plausible on your site, or verify your installation manually"},
+ "Make sure you've initialized Plausible on your site, or verify your installation manually"},
{"manual",
- "Please make sure you've copied the snippet to the head of your site, or verify your installation manually"}
+ "Make sure you've copied the snippet to the head of your site, or verify your installation manually"}
] do
test "returns error \"We couldn't detect Plausible on your site\" when plausible_is_on_window is false (with best guess recommendation for installation type: #{installation_type})" do
verification_stub =
@@ -484,7 +480,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
- errors: [^any(:string, ~r/.*temporary service error.*/)],
+ errors: [^any(:string, ~r/.*temporarily unavailable.*/)],
recommendations: [
%{
text: ^any(:string, ~r/.*in a few minutes.*/),
@@ -514,7 +510,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
assert_matches %Result{
ok?: false,
- errors: [^any(:string, ~r/.*temporary service error.*/)],
+ errors: [^any(:string, ~r/.*temporarily unavailable.*/)],
recommendations: [
%{
text: ^any(:string, ~r/.*in a few minutes.*/),
diff --git a/test/plausible_web/live/components/verification_banner_test.exs b/test/plausible_web/live/components/verification_banner_test.exs
index 61e1a34af423..1ee61a94a8c5 100644
--- a/test/plausible_web/live/components/verification_banner_test.exs
+++ b/test/plausible_web/live/components/verification_banner_test.exs
@@ -11,9 +11,8 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
@component PlausibleWeb.Live.Components.VerificationBanner
@progress ~s|#verification-ui p#progress|
- @loading_spinner ~s|div#verification-ui div.loading|
- @check_circle ~s|div#verification-ui #check-circle|
- @error_circle ~s|div#verification-ui #error-circle|
+ @loading_spinner ~s|#verification-ui svg.animate-spin|
+ @check_circle ~s|#verification-ui #check-circle|
@recommendations ~s|#recommendation|
@super_admin_report ~s|#super-admin-report|
@@ -22,24 +21,23 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
assert element_exists?(html, @progress)
assert text_of_element(html, @progress) ==
- "We're visiting your site to ensure that everything is working"
+ "We're visiting your site to ensure that everything is working..."
assert element_exists?(html, @loading_spinner)
- refute class_of_element(html, @loading_spinner) =~ "hidden"
refute element_exists?(html, @recommendations)
refute element_exists?(html, @check_circle)
refute element_exists?(html, @super_admin_report)
end
- test "renders error badge on error" do
+ test "renders failed state without progress spinner" do
html = render_component(@component, domain: "example.com", success?: false, finished?: true)
refute element_exists?(html, @loading_spinner)
refute element_exists?(html, @check_circle)
refute element_exists?(html, @recommendations)
- assert element_exists?(html, @error_circle)
+ assert html =~ "We couldn't verify your installation"
end
- test "renders diagnostic interpretation" do
+ test "renders diagnostic interpretation with inline verify/review links" do
interpretation =
Verification.Checks.interpret_diagnostics(%State{
url: "https://example.com",
@@ -56,11 +54,58 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
)
assert [recommendation] = html |> find(@recommendations) |> Enum.map(&text/1)
- assert recommendation =~ "check that the domain you entered is correct"
+ assert recommendation =~ "Check that the URL is correct and publicly accessible"
+ assert recommendation =~ "verify your installation manually"
+ assert recommendation =~ "review your installation"
+
+ assert element_exists?(
+ html,
+ ~s|#recommendation a[href="https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"]|
+ )
+
+ assert element_exists?(
+ html,
+ ~s|#recommendation a[href="/example.com/installation?flow="]|
+ )
refute element_exists?(html, @super_admin_report)
end
+ test "renders inline verify-manually link when the recommendation mentions it (no custom URL retry)" do
+ interpretation =
+ Verification.Checks.interpret_diagnostics(%State{
+ url: "https://example.com",
+ data_domain: "example.com",
+ diagnostics: %Verification.Diagnostics{
+ plausible_is_on_window: false,
+ selected_installation_type: "manual"
+ }
+ })
+
+ refute Map.get(interpretation.data || %{}, :offer_custom_url_input) == true
+
+ html =
+ render_component(@component,
+ domain: "example.com",
+ success?: false,
+ finished?: true,
+ interpretation: interpretation
+ )
+
+ assert [recommendation] = html |> find(@recommendations) |> Enum.map(&text/1)
+ assert recommendation =~ "Make sure you've copied the snippet"
+ assert recommendation =~ "verify your installation manually"
+ refute recommendation =~ "review your installation"
+ refute recommendation =~ "Learn more"
+
+ assert element_exists?(
+ html,
+ ~s|#recommendation a[href="https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"]|
+ )
+
+ refute element_exists?(html, ~s|#recommendation a[href^="/example.com/installation"]|)
+ end
+
test "renders super-admin report" do
state = %State{
url: "https://example.com",
@@ -99,20 +144,20 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
test "renders a progress message" do
html = render_component(@component, domain: "example.com", message: "Arbitrary message")
- assert text_of_element(html, @progress) == "Arbitrary message"
+ assert text_of_element(html, @progress) == "Arbitrary message..."
end
- test "renders contact link on >3 attempts" do
+ test "renders contact link on >=3 attempts" do
html = render_component(@component, domain: "example.com", attempts: 2, finished?: true)
- refute html =~ "Need further help with your installation?"
+ refute html =~ "Need help?"
refute element_exists?(html, ~s|a[href="https://plausible.io/contact"]|)
html = render_component(@component, domain: "example.com", attempts: 3, finished?: true)
- assert html =~ "Need further help with your installation?"
+ assert html =~ "Need help?"
assert element_exists?(html, ~s|a[href="https://plausible.io/contact"]|)
end
- test "renders a click-to-show-form link to verify installation at a different URL" do
+ test "renders a Try another URL ghost button when a custom URL retry is offered" do
interpretation =
Verification.Checks.interpret_diagnostics(%State{
url: "example.com",
@@ -133,11 +178,12 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
interpretation: interpretation
)
- assert text_of_element(html, "#verify-custom-url-link") =~ "Click here"
+ assert text_of_element(html, "#verify-custom-url-link") =~ "Try another URL"
assert element_exists?(html, ~s|a#verify-custom-url-link[phx-click="show-custom-url-form"]|)
+ refute html =~ "Review installation"
end
- test "renders the custom URL input inline, retry button becomes the form's submit button, hides the prompt link" do
+ test "renders the custom URL input inline, replacing Check again with the Verify URL submit button, and hides the secondary action" do
interpretation =
Verification.Checks.interpret_diagnostics(%State{
url: "example.com",
@@ -159,9 +205,10 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
refute element_exists?(html, "#verify-custom-url-link")
refute element_exists?(html, ~s|a[phx-click="retry"]|)
+ refute html =~ "Review installation"
assert text_of_element(html, ~s|form[phx-submit="verify-custom-url"] button[type="submit"]|) =~
- "Check again"
+ "Verify URL"
assert element_exists?(
html,
@@ -172,13 +219,12 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
"https://example.com"
end
- test "offers an installation-instructions escape path on failure, no more settings link" do
+ test "offers a Review installation ghost button on failure by default" do
html =
render_component(@component,
domain: "example.com",
success?: false,
finished?: true,
- installation_type: "wordpress",
flow: PlausibleWeb.Flows.review()
)
@@ -188,6 +234,8 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
html,
~s|a[href="/example.com/installation?flow=review"]|
)
+
+ assert html =~ "Review installation"
end
end
end
diff --git a/test/plausible_web/live/verification_test.exs b/test/plausible_web/live/verification_test.exs
index 896b5edc46ca..4ba6ea3f823c 100644
--- a/test/plausible_web/live/verification_test.exs
+++ b/test/plausible_web/live/verification_test.exs
@@ -132,7 +132,7 @@ defmodule PlausibleWeb.Live.VerificationTest do
assert eventually(fn ->
html = render(lv)
- {html =~ "Success!", html}
+ {html =~ "Tracking is active on your site", html}
end)
end
@@ -174,7 +174,7 @@ defmodule PlausibleWeb.Live.VerificationTest do
# must stay hidden.
assert eventually(fn ->
html = render(lv)
- {html =~ "Success!", html}
+ {html =~ "Tracking is active on your site", html}
end)
html = render(lv)
@@ -199,16 +199,16 @@ defmodule PlausibleWeb.Live.VerificationTest do
end
for {expected_text, saved_installation_type} <- [
- {"Please make sure you've copied the snippet to the head of your site, or verify your installation manually.",
+ {"Make sure you've copied the snippet to the head of your site, or verify your installation manually.",
"manual"},
- {"Please make sure you've initialized Plausible on your site, or verify your installation manually.",
+ {"Make sure you've initialized Plausible on your site, or verify your installation manually.",
"npm"},
- {"Please make sure you've configured the GTM template correctly, or verify your installation manually.",
+ {"Make sure you've configured the GTM template correctly, or verify your installation manually.",
"gtm"},
- {"Please make sure you've enabled the plugin, or verify your installation manually.",
+ {"Make sure you've enabled the WordPress plugin, or verify your installation manually.",
"wordpress"},
# falls back to manual when there's no saved installation type
- {"Please make sure you've copied the snippet to the head of your site, or verify your installation manually.",
+ {"Make sure you've copied the snippet to the head of your site, or verify your installation manually.",
nil}
] do
@tag :ee_only
@@ -246,7 +246,7 @@ defmodule PlausibleWeb.Live.VerificationTest do
assert element_exists?(html, @retry_button)
- assert html =~ htmlize_quotes(unquote(expected_text))
+ assert text_of_element(html, "#recommendation") =~ unquote(expected_text)
refute element_exists?(html, "#super-admin-report")
end
end
From 49a1ecd5b907baf2f34da8ea61e415d27f513870 Mon Sep 17 00:00:00 2001
From: Robert Joonas
Date: Wed, 22 Jul 2026 13:58:48 +0100
Subject: [PATCH 2/2] improve templating logic
---
.../plausible/installation_support/result.ex | 2 +-
.../verification/diagnostics.ex | 95 ++++++++++++-------
.../live/components/verification_banner.ex | 90 ++++++------------
.../verification/checks_test.exs | 82 +++++++++-------
.../verification/diagnostics_test.exs | 46 +++++++++
.../components/verification_banner_test.exs | 6 +-
6 files changed, 189 insertions(+), 132 deletions(-)
create mode 100644 test/plausible/installation_support/verification/diagnostics_test.exs
diff --git a/extra/lib/plausible/installation_support/result.ex b/extra/lib/plausible/installation_support/result.ex
index baa08d645ddd..a1fad54ca56b 100644
--- a/extra/lib/plausible/installation_support/result.ex
+++ b/extra/lib/plausible/installation_support/result.ex
@@ -6,7 +6,7 @@ defmodule Plausible.InstallationSupport.Result do
ok?: false,
data: nil,
errors: [error.message],
- recommendations: [%{text: error.recommendation, url: error.url}]
+ recommendations: [%{text: error.recommendation, inline_links: error.inline_links}]
ok?: true,
data: %{},
diff --git a/extra/lib/plausible/installation_support/verification/diagnostics.ex b/extra/lib/plausible/installation_support/verification/diagnostics.ex
index 75d2d66cd9e6..d464a0155fda 100644
--- a/extra/lib/plausible/installation_support/verification/diagnostics.ex
+++ b/extra/lib/plausible/installation_support/verification/diagnostics.ex
@@ -33,35 +33,56 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
"""
@enforce_keys [:message, :recommendation]
- defstruct [:message, :recommendation, :url]
+ defstruct [:message, :recommendation, inline_links: []]
+
+ @required_link_prefix "https://plausible.io/"
def new!(attrs) do
message = Map.fetch!(attrs, :message)
+ recommendation = Map.fetch!(attrs, :recommendation)
+ inline_links = Map.get(attrs, :inline_links, [])
if String.ends_with?(message, ".") do
raise ArgumentError, "Error message must not end with a period: #{inspect(message)}"
end
- if String.ends_with?(attrs[:recommendation], ".") do
+ if String.ends_with?(recommendation, ".") do
raise ArgumentError,
- "Error recommendation must not end with a period: #{inspect(attrs[:recommendation])}"
+ "Error recommendation must not end with a period: #{inspect(recommendation)}"
end
- if is_binary(attrs[:url]) and not String.starts_with?(attrs[:url], "https://plausible.io") do
- raise ArgumentError,
- "Recommendation url must start with 'https://plausible.io': #{inspect(attrs[:url])}"
+ for %{text: text, href: href} <- inline_links do
+ if length(String.split(recommendation, text)) - 1 != 1 do
+ raise ArgumentError,
+ "Recommendation inline_links text #{inspect(text)} must appear exactly once in: #{inspect(recommendation)}"
+ end
+
+ if not String.starts_with?(href, @required_link_prefix) do
+ raise ArgumentError,
+ "Recommendation inline_links href must start with '#{@required_link_prefix}': #{inspect(href)}"
+ end
end
struct!(__MODULE__, attrs)
end
end
+ @verify_manually_inline_link %{
+ text: "verify your installation manually",
+ href: @verify_manually_url
+ }
+
@error_succeeds_only_after_cache_bust Error.new!(%{
message: "We detected an issue with your site's cache",
recommendation:
- "Clear the cache for your site to ensure your visitors load the latest version of your site with Plausible correctly installed",
- url:
- "https://plausible.io/docs/troubleshoot-integration#have-you-cleared-the-cache-of-your-site"
+ "Clear the cache for your site to ensure your visitors load the latest version of your site with Plausible correctly installed. Learn more",
+ inline_links: [
+ %{
+ text: "Learn more",
+ href:
+ "https://plausible.io/docs/troubleshoot-integration#have-you-cleared-the-cache-of-your-site"
+ }
+ ]
})
@spec interpret(t(), String.t(), String.t()) :: Result.t()
@@ -123,14 +144,19 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_proxy_network_error Error.new!(%{
message: "We couldn't verify your proxied installation",
recommendation:
- "We received an unexpected response from your proxy. Check that you've configured the proxied /event route correctly",
- url: "https://plausible.io/docs/proxy/introduction"
+ "We received an unexpected response from your proxy. Check that you've configured the proxied /event route correctly. Learn more",
+ inline_links: [
+ %{
+ text: "Learn more",
+ href: "https://plausible.io/docs/proxy/introduction"
+ }
+ ]
})
@error_plausible_network_error Error.new!(%{
message: "We couldn't verify your website",
recommendation:
"Please try verifying again in a few minutes, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
def interpret(
@@ -175,9 +201,14 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
message:
"Your site's Content Security Policy (CSP) is blocking Plausible",
recommendation:
- "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics",
- url:
- "https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
+ "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics. Learn more",
+ inline_links: [
+ %{
+ text: "Learn more",
+ href:
+ "https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
+ }
+ ]
})
def interpret(
%__MODULE__{
@@ -192,8 +223,8 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_domain_not_found Error.new!(%{
message: "We couldn't reach <%= @attempted_url %>",
recommendation:
- "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
- url: @verify_manually_url
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you'll need to verify your installation manually",
+ inline_links: [@verify_manually_inline_link]
})
def interpret(%__MODULE__{service_error: %{code: code}}, expected_domain, url)
@@ -208,8 +239,8 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_browserless_network Error.new!(%{
message: "We couldn't verify <%= @attempted_url %>",
recommendation:
- "We encountered a network error while trying to access your website. You can verify your installation manually or review your installation",
- url: @verify_manually_url
+ "We encountered a network error while trying to access your website. You can verify your installation manually",
+ inline_links: [@verify_manually_inline_link]
})
def interpret(
@@ -229,7 +260,7 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
message: "Our verification service is temporarily unavailable",
recommendation:
"Please try again in a few minutes or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
def interpret(%__MODULE__{service_error: %{code: code}}, _expected_domain, _url)
@@ -240,8 +271,8 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
@error_unexpected_page_response Error.new!(%{
message: "We couldn't verify <%= @attempted_url %>",
recommendation:
- "Accessing your website returned an unexpected status code (<%= @page_response_status %>). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually or review your installation",
- url: @verify_manually_url
+ "Accessing your website returned an unexpected status code (<%= @page_response_status %>). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually",
+ inline_links: [@verify_manually_inline_link]
})
def interpret(
@@ -287,25 +318,25 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
message: @message_plausible_not_found,
recommendation:
"Make sure you've copied the snippet to the head of your site, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_plausible_not_found_for_npm Error.new!(%{
message: @message_plausible_not_found,
recommendation:
"Make sure you've initialized Plausible on your site, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_plausible_not_found_for_gtm Error.new!(%{
message: @message_plausible_not_found,
recommendation:
"Make sure you've configured the GTM template correctly, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_plausible_not_found_for_wordpress Error.new!(%{
message: @message_plausible_not_found,
recommendation:
"Make sure you've enabled the WordPress plugin, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
defp error_plausible_not_found(selected_installation_type) do
case selected_installation_type do
@@ -321,28 +352,28 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
message: @unexpected_domain_message,
recommendation:
"Check that the snippet on your site matches the one shown in the installation instructions, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_unexpected_domain_for_npm Error.new!(%{
message: @unexpected_domain_message,
recommendation:
"Check you've initialized Plausible with the correct domain, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_unexpected_domain_for_gtm Error.new!(%{
message: @unexpected_domain_message,
recommendation:
"Check you've entered the ID in the GTM template correctly, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
@error_unexpected_domain_for_wordpress Error.new!(%{
message: @unexpected_domain_message,
recommendation:
"Check you've installed the WordPress plugin correctly, or verify your installation manually",
- url: @verify_manually_url
+ inline_links: [@verify_manually_inline_link]
})
defp error_unexpected_domain(selected_installation_type) do
case selected_installation_type do
@@ -368,7 +399,7 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
%Result{
ok?: false,
errors: [message],
- recommendations: [%{text: recommendation, url: error.url}]
+ recommendations: [%{text: recommendation, inline_links: error.inline_links}]
}
end
@@ -379,7 +410,7 @@ defmodule Plausible.InstallationSupport.Verification.Diagnostics do
ok?: false,
data: %{unhandled: true, browserless_issue: browserless_issue},
errors: [error.message],
- recommendations: [%{text: error.recommendation, url: error.url}]
+ recommendations: [%{text: error.recommendation, inline_links: error.inline_links}]
}
end
end
diff --git a/lib/plausible_web/live/components/verification_banner.ex b/lib/plausible_web/live/components/verification_banner.ex
index 12c355af2094..b40731c01db9 100644
--- a/lib/plausible_web/live/components/verification_banner.ex
+++ b/lib/plausible_web/live/components/verification_banner.ex
@@ -206,22 +206,14 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
defp recommendation(assigns) do
recommendation = List.first(assigns.interpretation.recommendations)
-
- review_installation_url =
- Routes.site_path(
- PlausibleWeb.Endpoint,
- :installation,
- assigns.domain,
- flow: assigns.flow
- )
+ main = render_recommendation(recommendation.text, recommendation.inline_links)
body =
- recommendation_body(
- recommendation.text,
- recommendation.url,
- review_installation_url,
- assigns.offer_custom_url_input?
- )
+ if assigns.offer_custom_url_input? do
+ [main, ". ", review_installation_link_sentence(assigns), "."]
+ else
+ [main, "."]
+ end
assigns = assign(assigns, :body, body)
@@ -232,49 +224,31 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
"""
end
- @verify_manually_phrase "verify your installation manually"
- @both_phrases "verify your installation manually or review your installation"
-
- defp recommendation_body(
- text,
- verify_manually_url,
- review_installation_url,
- offer_custom_url_input?
- ) do
- cond do
- offer_custom_url_input? and String.contains?(text, @both_phrases) ->
- [leading, _rest] = String.split(text, @both_phrases, parts: 2)
-
- [
- leading,
- external_link("verify your installation manually", verify_manually_url),
- " or ",
- internal_link("review your installation", review_installation_url),
- "."
- ]
-
- String.contains?(text, @verify_manually_phrase) ->
- [leading, _rest] = String.split(text, @verify_manually_phrase, parts: 2)
-
- [
- leading,
- external_link("verify your installation manually", verify_manually_url),
- "."
- ]
-
- true ->
- [text, ". ", external_link("Learn more", verify_manually_url)]
- end
+ defp render_recommendation(text, inline_links) do
+ html =
+ Enum.reduce(inline_links, html_escape(text), fn %{text: link_text, href: href}, acc ->
+ String.replace(acc, link_text, link_markup(link_text, href), global: false)
+ end)
+
+ Phoenix.HTML.raw(html)
end
- defp external_link(text, url) do
- Phoenix.HTML.raw(
- ~s|#{html_escape(text)}|
- )
+ defp review_installation_link_sentence(assigns) do
+ review_installation_url =
+ Routes.site_path(PlausibleWeb.Endpoint, :installation, assigns.domain, flow: assigns.flow)
+
+ render_recommendation("See your installation instructions again here", [
+ %{text: "here", href: review_installation_url}
+ ])
end
- defp internal_link(text, url) do
- Phoenix.HTML.raw(~s|#{html_escape(text)}|)
+ defp link_markup(text, href) do
+ external_attrs =
+ if String.starts_with?(href, "http"),
+ do: ~s| target="_blank" rel="noopener noreferrer"|,
+ else: ""
+
+ ~s|#{html_escape(text)}|
end
defp html_escape(value) do
@@ -320,15 +294,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBanner do
defp contact_us_link(assigns) do
~H"""
- Need help?
-
- Contact us
-
+ Need help? {Phoenix.HTML.raw(link_markup("Contact us", "https://plausible.io/contact"))}
"""
end
diff --git a/test/plausible/installation_support/verification/checks_test.exs b/test/plausible/installation_support/verification/checks_test.exs
index e53c569880fd..b9e0bde8e134 100644
--- a/test/plausible/installation_support/verification/checks_test.exs
+++ b/test/plausible/installation_support/verification/checks_test.exs
@@ -13,6 +13,11 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
@expected_domain "example.com"
@url_to_verify "https://#{@expected_domain}"
+ @verify_manually_url "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ @verify_manually_inline_link %{
+ text: "verify your installation manually",
+ href: @verify_manually_url
+ }
describe "URL check" do
test "returns error when DNS check fails with domain not found error, offers custom URL input" do
@@ -27,9 +32,8 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -54,9 +58,8 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually or review your installation",
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ "Check that the URL is correct and publicly accessible. If your site is intentionally private, you can verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -123,8 +126,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text: unquote(expected_recommendation),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -158,7 +160,12 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text: ^any(:string, ~r/.*proxied.*/),
- url: "https://plausible.io/docs/proxy/introduction"
+ inline_links: [
+ %{
+ text: "Learn more",
+ href: "https://plausible.io/docs/proxy/introduction"
+ }
+ ]
}
]
} =
@@ -187,9 +194,9 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
errors: [^any(:string, ~r/.*couldn't verify.*/)],
recommendations: [
%{
- text: ^any(:string, ~r/.*try verifying again.*/),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ text:
+ "Please try verifying again in a few minutes, or verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -214,8 +221,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
%{
text:
"Make sure you've copied the snippet to the head of your site, or verify your installation manually",
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -241,9 +247,14 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics",
- url:
- "https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
+ "Add plausible.io to the list of allowed domains in your site's Content Security Policy to allow Plausible to collect analytics. Learn more",
+ inline_links: [
+ %{
+ text: "Learn more",
+ href:
+ "https://plausible.io/docs/troubleshoot-integration#does-your-site-use-a-content-security-policy-csp"
+ }
+ ]
}
]
} =
@@ -265,9 +276,8 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "We encountered a network error while trying to access your website. You can verify your installation manually or review your installation",
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ "We encountered a network error while trying to access your website. You can verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -293,9 +303,8 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text:
- "Accessing your website returned an unexpected status code (403). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually or review your installation",
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ "Accessing your website returned an unexpected status code (403). Check for anything that might be blocking our access to your site, such as a firewall, authentication requirements, or CDN rules. You can also verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -330,8 +339,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text: unquote(expected_recommendation),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -359,8 +367,7 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text: unquote(expected_recommendation),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ inline_links: [^@verify_manually_inline_link]
}
]
} =
@@ -422,8 +429,13 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
recommendations: [
%{
text: ^any(:string, ~r/.*cache.*/),
- url:
- "https://plausible.io/docs/troubleshoot-integration#have-you-cleared-the-cache-of-your-site"
+ inline_links: [
+ %{
+ text: "Learn more",
+ href:
+ "https://plausible.io/docs/troubleshoot-integration#have-you-cleared-the-cache-of-your-site"
+ }
+ ]
}
]
} = run_checks(verification_stub) |> Checks.interpret_diagnostics()
@@ -483,9 +495,9 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
errors: [^any(:string, ~r/.*temporarily unavailable.*/)],
recommendations: [
%{
- text: ^any(:string, ~r/.*in a few minutes.*/),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ text:
+ "Please try again in a few minutes or verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} = Checks.interpret_diagnostics(state)
@@ -513,9 +525,9 @@ defmodule Plausible.InstallationSupport.Verification.ChecksTest do
errors: [^any(:string, ~r/.*temporarily unavailable.*/)],
recommendations: [
%{
- text: ^any(:string, ~r/.*in a few minutes.*/),
- url:
- "https://plausible.io/docs/troubleshoot-integration#how-to-manually-check-your-integration"
+ text:
+ "Please try again in a few minutes or verify your installation manually",
+ inline_links: [^@verify_manually_inline_link]
}
]
} = Checks.interpret_diagnostics(state)
diff --git a/test/plausible/installation_support/verification/diagnostics_test.exs b/test/plausible/installation_support/verification/diagnostics_test.exs
new file mode 100644
index 000000000000..bead8dfa1df0
--- /dev/null
+++ b/test/plausible/installation_support/verification/diagnostics_test.exs
@@ -0,0 +1,46 @@
+defmodule Plausible.InstallationSupport.Verification.DiagnosticsTest do
+ use ExUnit.Case, async: true
+
+ alias Plausible.InstallationSupport.Verification.Diagnostics.Error
+
+ describe "Error.new!/1" do
+ test "accepts a recommendation whose inline_links text appears exactly once" do
+ assert %Error{} =
+ Error.new!(%{
+ message: "Something went wrong",
+ recommendation: "Check the docs for more info",
+ inline_links: [%{text: "docs", href: "https://plausible.io/docs"}]
+ })
+ end
+
+ test "raises when inline_links text isn't found in the recommendation" do
+ assert_raise ArgumentError, ~r/must appear exactly once/, fn ->
+ Error.new!(%{
+ message: "Something went wrong",
+ recommendation: "Check the manual for more info",
+ inline_links: [%{text: "docs", href: "https://plausible.io/docs"}]
+ })
+ end
+ end
+
+ test "raises when inline_links text appears more than once in the recommendation" do
+ assert_raise ArgumentError, ~r/must appear exactly once/, fn ->
+ Error.new!(%{
+ message: "Something went wrong",
+ recommendation: "Check the docs, or check the docs again",
+ inline_links: [%{text: "the docs", href: "https://plausible.io/docs"}]
+ })
+ end
+ end
+
+ test "raises when inline_links href doesn't point at plausible.io" do
+ assert_raise ArgumentError, ~r/must start with/, fn ->
+ Error.new!(%{
+ message: "Something went wrong",
+ recommendation: "Check the docs for more info",
+ inline_links: [%{text: "docs", href: "https://example.com/docs"}]
+ })
+ end
+ end
+ end
+end
diff --git a/test/plausible_web/live/components/verification_banner_test.exs b/test/plausible_web/live/components/verification_banner_test.exs
index 1ee61a94a8c5..0ecdf1bc8a58 100644
--- a/test/plausible_web/live/components/verification_banner_test.exs
+++ b/test/plausible_web/live/components/verification_banner_test.exs
@@ -37,7 +37,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
assert html =~ "We couldn't verify your installation"
end
- test "renders diagnostic interpretation with inline verify/review links" do
+ test "renders diagnostic interpretation with inline verify link and standalone review-installation sentence" do
interpretation =
Verification.Checks.interpret_diagnostics(%State{
url: "https://example.com",
@@ -56,7 +56,8 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
assert [recommendation] = html |> find(@recommendations) |> Enum.map(&text/1)
assert recommendation =~ "Check that the URL is correct and publicly accessible"
assert recommendation =~ "verify your installation manually"
- assert recommendation =~ "review your installation"
+ refute recommendation =~ "review your installation"
+ assert recommendation =~ "See your installation instructions again here"
assert element_exists?(
html,
@@ -97,6 +98,7 @@ defmodule PlausibleWeb.Live.Components.VerificationBannerTest do
assert recommendation =~ "verify your installation manually"
refute recommendation =~ "review your installation"
refute recommendation =~ "Learn more"
+ refute recommendation =~ "See your installation instructions again here"
assert element_exists?(
html,