diff --git a/fixture/ga4_get_property.json b/fixture/ga4_get_property.json new file mode 100644 index 0000000000..ed98cc2240 --- /dev/null +++ b/fixture/ga4_get_property.json @@ -0,0 +1,12 @@ +{ + "account": "accounts/28425555", + "createTime": "2024-02-22T10:50:15.462Z", + "currencyCode": "USD", + "displayName": "account.one - GA4", + "name": "properties/428685444", + "parent": "accounts/28425555", + "propertyType": "PROPERTY_TYPE_ORDINARY", + "serviceLevel": "GOOGLE_ANALYTICS_STANDARD", + "timeZone": "Europe/Warsaw", + "updateTime": "2024-02-22T10:50:15.462Z" +} \ No newline at end of file diff --git a/fixture/ga_start_date.json b/fixture/ga_start_date.json new file mode 100644 index 0000000000..eb72f5d5ea --- /dev/null +++ b/fixture/ga_start_date.json @@ -0,0 +1,38 @@ +{ + "reports": [ + { + "columnHeader": { + "dimensions": [ + "ga:date" + ], + "metricHeader": { + "metricHeaderEntries": [ + { + "name": "ga:pageviews", + "type": "INTEGER" + } + ] + } + }, + "data": { + "isDataGolden": true, + "rowCount": 849, + "rows": [ + { + "dimensions": [ + "20120118" + ], + "metrics": [ + { + "values": [ + "37" + ] + } + ] + } + ] + }, + "nextPageToken": "1" + } + ] +} \ No newline at end of file diff --git a/lib/plausible/google/api.ex b/lib/plausible/google/api.ex index 6b1e44b4ea..f2ed4e9295 100644 --- a/lib/plausible/google/api.ex +++ b/lib/plausible/google/api.ex @@ -23,16 +23,38 @@ defmodule Plausible.Google.API do def import_authorize_url(site_id, redirect_to, opts \\ []) do legacy = Keyword.get(opts, :legacy, true) - ga4 = Keyword.get(opts, :ga4, false) "https://accounts.google.com/o/oauth2/v2/auth?client_id=#{client_id()}&redirect_uri=#{redirect_uri()}&prompt=consent&response_type=code&access_type=offline&scope=#{@import_scope}&state=" <> - Jason.encode!([site_id, redirect_to, legacy, ga4]) + Jason.encode!([site_id, redirect_to, legacy]) end def fetch_access_token!(code) do HTTP.fetch_access_token!(code) end + def list_properties_and_views(access_token) do + with {:ok, properties} <- Plausible.Google.GA4.API.list_properties(access_token), + {:ok, views} <- Plausible.Google.UA.API.list_views(access_token) do + {:ok, properties ++ views} + end + end + + def get_property_or_view(access_token, property_or_view) do + if property?(property_or_view) do + Plausible.Google.GA4.API.get_property(access_token, property_or_view) + else + Plausible.Google.UA.API.get_view(access_token, property_or_view) + end + end + + def get_analytics_start_date(access_token, property_or_view) do + if property?(property_or_view) do + Plausible.Google.GA4.API.get_analytics_start_date(access_token, property_or_view) + else + Plausible.Google.UA.API.get_analytics_start_date(access_token, property_or_view) + end + end + def fetch_verified_properties(auth) do with {:ok, access_token} <- maybe_refresh_token(auth), {:ok, sites} <- Plausible.Google.HTTP.list_sites(access_token) do @@ -90,6 +112,8 @@ defmodule Plausible.Google.API do end end + def property?(value), do: String.starts_with?(value, "properties/") + defp do_refresh_token(refresh_token) do case HTTP.refresh_auth_token(refresh_token) do {:ok, %{"access_token" => new_access_token, "expires_in" => expires_in}} -> diff --git a/lib/plausible/google/ga4/api.ex b/lib/plausible/google/ga4/api.ex index f9062d00e3..10e29ed84a 100644 --- a/lib/plausible/google/ga4/api.ex +++ b/lib/plausible/google/ga4/api.ex @@ -25,29 +25,35 @@ defmodule Plausible.Google.GA4.API do accounts |> Enum.filter(& &1["propertySummaries"]) |> Enum.map(fn account -> - {"#{account["displayName"]} (#{account["account"]})", + %{"account" => account_id, "displayName" => account_name} = account + + {"#{account_name} (#{account_id})", Enum.map(account["propertySummaries"], fn property -> - {"#{property["displayName"]} (#{property["property"]})", property["property"]} + %{"displayName" => property_name, "property" => property_id} = property + + {"#{property_name} (#{property_id})", property_id} end)} end) {:ok, accounts} - error -> - error + {:error, cause} -> + {:error, cause} end end def get_property(access_token, lookup_property) do - case list_properties(access_token) do - {:ok, properties} -> - property = - properties - |> Enum.map(&elem(&1, 1)) - |> List.flatten() - |> Enum.find(fn {_name, property} -> property == lookup_property end) + case GA4.HTTP.get_property(access_token, lookup_property) do + {:ok, property} -> + %{"displayName" => property_name, "name" => property_id, "account" => account_id} = + property - {:ok, property} + {:ok, + %{ + id: property_id, + name: "#{property_name} (#{property_id})", + account_id: account_id + }} {:error, cause} -> {:error, cause} diff --git a/lib/plausible/google/ga4/http.ex b/lib/plausible/google/ga4/http.ex index da9ace19b2..60c69a5274 100644 --- a/lib/plausible/google/ga4/http.ex +++ b/lib/plausible/google/ga4/http.ex @@ -49,9 +49,8 @@ defmodule Plausible.Google.GA4.HTTP do ) with {:ok, %{body: body}} <- response, - # File.write!("fixture/ga4_report_#{report_request.dataset}.json", Jason.encode!(body)), {:ok, report} <- parse_report_from_response(body), - row_count <- Map.get(report, "rowCount"), + row_count <- Map.fetch!(report, "rowCount"), {:ok, report} <- convert_to_maps(report) do {:ok, {report, row_count}} else @@ -130,7 +129,7 @@ defmodule Plausible.Google.GA4.HTTP do end def list_accounts_for_user(access_token) do - url = "#{admin_api_url()}/v1beta/accountSummaries" + url = "#{admin_api_url()}/v1beta/accountSummaries?pageSize=200" headers = [{"Authorization", "Bearer #{access_token}"}] @@ -147,6 +146,30 @@ defmodule Plausible.Google.GA4.HTTP do end end + def get_property(access_token, property) do + url = "#{admin_api_url()}/v1beta/#{property}" + + headers = [{"Authorization", "Bearer #{access_token}"}] + + case HTTPClient.impl().get(url, headers) do + {:ok, %Finch.Response{body: body, status: 200}} -> + {:ok, body} + + {:error, %HTTPClient.Non200Error{} = error} when error.reason.status in [401, 403] -> + {:error, :authentication_failed} + + {:error, %HTTPClient.Non200Error{} = error} when error.reason.status in [404] -> + {:error, :not_found} + + {:error, %HTTPClient.Non200Error{} = error} -> + Sentry.capture_message("Error retrieving Google property #{property}", + extra: %{error: error} + ) + + {:error, :unknown} + end + end + @earliest_valid_date "2015-08-14" def get_analytics_start_date(access_token, property) do params = %{ diff --git a/lib/plausible/google/ua/api.ex b/lib/plausible/google/ua/api.ex index 47d2cebebf..5a38960a5d 100644 --- a/lib/plausible/google/ua/api.ex +++ b/lib/plausible/google/ua/api.ex @@ -26,7 +26,11 @@ defmodule Plausible.Google.UA.API do def list_views(access_token) do case UA.HTTP.list_views_for_user(access_token) do {:ok, %{"items" => views}} -> - views = Enum.group_by(views, &view_hostname/1, &view_names/1) + views = + views + |> Enum.group_by(&view_hostname/1, &view_names/1) + |> Enum.sort_by(fn {key, _} -> key end) + {:ok, views} error -> @@ -40,18 +44,19 @@ defmodule Plausible.Google.UA.API do Returns a single Google Analytics view if the user has access to it. """ def get_view(access_token, lookup_id) do - case list_views(access_token) do - {:ok, views} -> - view = - views - |> Map.values() - |> List.flatten() - |> Enum.find(fn {_name, id} -> id == lookup_id end) + with {:ok, views} <- list_views(access_token) do + views = + views + |> Enum.map(&elem(&1, 1)) + |> List.flatten() - {:ok, view} + case Enum.find(views, fn {_name, id} -> id == lookup_id end) do + {view_name, view_id} -> + {:ok, %{id: view_id, name: "#{view_name}"}} - {:error, cause} -> - {:error, cause} + nil -> + {:error, :not_found} + end end end diff --git a/lib/plausible/google/ua/http.ex b/lib/plausible/google/ua/http.ex index f00712f5ec..9d63abfe10 100644 --- a/lib/plausible/google/ua/http.ex +++ b/lib/plausible/google/ua/http.ex @@ -136,7 +136,7 @@ defmodule Plausible.Google.UA.HTTP do url = "#{reporting_api_url()}/v4/reports:batchGet" headers = [{"Authorization", "Bearer #{access_token}"}] - case HTTPClient.post(url, headers, params) do + case HTTPClient.impl().post(url, headers, params) do {:ok, %Finch.Response{body: body, status: 200}} -> report = List.first(body["reports"]) diff --git a/lib/plausible_web/controllers/auth_controller.ex b/lib/plausible_web/controllers/auth_controller.ex index a242413710..7844d5771f 100644 --- a/lib/plausible_web/controllers/auth_controller.ex +++ b/lib/plausible_web/controllers/auth_controller.ex @@ -750,16 +750,13 @@ defmodule PlausibleWeb.AuthController do def google_auth_callback(conn, %{"code" => code, "state" => state}) do res = Plausible.Google.API.fetch_access_token!(code) - [site_id, redirect_to, legacy, ga4] = + [site_id, redirect_to, legacy] = case Jason.decode!(state) do [site_id, redirect_to] -> - [site_id, redirect_to, true, false] + [site_id, redirect_to, true] [site_id, redirect_to, legacy] -> - [site_id, redirect_to, legacy, false] - - [site_id, redirect_to, legacy, ga4] -> - [site_id, redirect_to, legacy, ga4] + [site_id, redirect_to, legacy] end site = Repo.get(Plausible.Site, site_id) @@ -767,26 +764,15 @@ defmodule PlausibleWeb.AuthController do case redirect_to do "import" -> - if ga4 do - redirect(conn, - external: - Routes.google_analytics4_path(conn, :property_form, site.domain, - access_token: res["access_token"], - refresh_token: res["refresh_token"], - expires_at: NaiveDateTime.to_iso8601(expires_at) - ) - ) - else - redirect(conn, - external: - Routes.universal_analytics_path(conn, :view_id_form, site.domain, - access_token: res["access_token"], - refresh_token: res["refresh_token"], - expires_at: NaiveDateTime.to_iso8601(expires_at), - legacy: legacy - ) - ) - end + redirect(conn, + external: + Routes.google_analytics_path(conn, :property_or_view_form, site.domain, + access_token: res["access_token"], + refresh_token: res["refresh_token"], + expires_at: NaiveDateTime.to_iso8601(expires_at), + legacy: legacy + ) + ) _ -> id_token = res["id_token"] diff --git a/lib/plausible_web/controllers/google_analytics4_controller.ex b/lib/plausible_web/controllers/google_analytics4_controller.ex deleted file mode 100644 index 3fd55d3ab6..0000000000 --- a/lib/plausible_web/controllers/google_analytics4_controller.ex +++ /dev/null @@ -1,143 +0,0 @@ -defmodule PlausibleWeb.GoogleAnalytics4Controller do - use PlausibleWeb, :controller - - plug(PlausibleWeb.RequireAccountPlug) - - plug(PlausibleWeb.AuthorizeSiteAccess, [:owner, :admin, :super_admin]) - - def property_form(conn, %{ - "access_token" => access_token, - "refresh_token" => refresh_token, - "expires_at" => expires_at - }) do - redirect_route = Routes.site_path(conn, :settings_imports_exports, conn.assigns.site.domain) - - case Plausible.Google.GA4.API.list_properties(access_token) do - {:ok, properties} -> - conn - |> assign(:skip_plausible_tracking, true) - |> render("property_form.html", - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at, - site: conn.assigns.site, - properties: properties, - layout: {PlausibleWeb.LayoutView, "focus.html"} - ) - - {:error, :authentication_failed} -> - conn - |> put_flash( - :error, - "We were unable to authenticate your Google Analytics account. Please check that you have granted us permission to 'See and download your Google Analytics data' and try again." - ) - |> redirect(external: redirect_route) - - {:error, _any} -> - conn - |> put_flash( - :error, - "We were unable to list your Google Analytics properties. If the problem persists, please contact support for assistance." - ) - |> redirect(external: redirect_route) - end - end - - def property(conn, %{ - "property" => property, - "access_token" => access_token, - "refresh_token" => refresh_token, - "expires_at" => expires_at - }) do - site = conn.assigns.site - start_date = Plausible.Google.GA4.API.get_analytics_start_date(access_token, property) - - case start_date do - {:ok, nil} -> - {:ok, properties} = Plausible.Google.GA4.API.list_properties(access_token) - - conn - |> assign(:skip_plausible_tracking, true) - |> render("property_form.html", - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at, - site: site, - properties: properties, - selected_property_error: "No data found. Nothing to import", - layout: {PlausibleWeb.LayoutView, "focus.html"} - ) - - {:ok, _date} -> - redirect(conn, - to: - Routes.google_analytics4_path(conn, :confirm, site.domain, - property: property, - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at - ) - ) - end - end - - def confirm(conn, %{ - "property" => property, - "access_token" => access_token, - "refresh_token" => refresh_token, - "expires_at" => expires_at - }) do - site = conn.assigns.site - - start_date = Plausible.Google.GA4.API.get_analytics_start_date(access_token, property) - - end_date = Plausible.Sites.native_stats_start_date(site) || Timex.today(site.timezone) - - {:ok, {property_name, property}} = - Plausible.Google.GA4.API.get_property(access_token, property) - - conn - |> assign(:skip_plausible_tracking, true) - |> render("confirm.html", - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at, - site: site, - selected_property: property, - selected_property_name: property_name, - start_date: start_date, - end_date: end_date, - layout: {PlausibleWeb.LayoutView, "focus.html"} - ) - end - - def import(conn, %{ - "property" => property, - "start_date" => start_date, - "end_date" => end_date, - "access_token" => access_token, - "refresh_token" => refresh_token, - "expires_at" => expires_at - }) do - site = conn.assigns.site - current_user = conn.assigns.current_user - - redirect_route = Routes.site_path(conn, :settings_imports_exports, site.domain) - - {:ok, _} = - Plausible.Imported.GoogleAnalytics4.new_import( - site, - current_user, - property: property, - start_date: start_date, - end_date: end_date, - access_token: access_token, - refresh_token: refresh_token, - token_expires_at: expires_at - ) - - conn - |> put_flash(:success, "Import scheduled. An email will be sent when it completes.") - |> redirect(external: redirect_route) - end -end diff --git a/lib/plausible_web/controllers/universal_analytics_controller.ex b/lib/plausible_web/controllers/google_analytics_controller.ex similarity index 59% rename from lib/plausible_web/controllers/universal_analytics_controller.ex rename to lib/plausible_web/controllers/google_analytics_controller.ex index 16a4bea64e..60d10df273 100644 --- a/lib/plausible_web/controllers/universal_analytics_controller.ex +++ b/lib/plausible_web/controllers/google_analytics_controller.ex @@ -1,4 +1,4 @@ -defmodule PlausibleWeb.UniversalAnalyticsController do +defmodule PlausibleWeb.GoogleAnalyticsController do use PlausibleWeb, :controller plug(PlausibleWeb.RequireAccountPlug) @@ -6,7 +6,7 @@ defmodule PlausibleWeb.UniversalAnalyticsController do plug(PlausibleWeb.AuthorizeSiteAccess, [:owner, :admin, :super_admin]) def user_metric_notice(conn, %{ - "view_id" => view_id, + "property_or_view" => property_or_view, "access_token" => access_token, "refresh_token" => refresh_token, "expires_at" => expires_at, @@ -18,7 +18,7 @@ defmodule PlausibleWeb.UniversalAnalyticsController do |> assign(:skip_plausible_tracking, true) |> render("user_metric_form.html", site: site, - view_id: view_id, + property_or_view: property_or_view, access_token: access_token, refresh_token: refresh_token, expires_at: expires_at, @@ -27,29 +27,38 @@ defmodule PlausibleWeb.UniversalAnalyticsController do ) end - def view_id_form(conn, %{ + def property_or_view_form(conn, %{ "access_token" => access_token, "refresh_token" => refresh_token, "expires_at" => expires_at, "legacy" => legacy }) do + site = conn.assigns.site + redirect_route = if legacy == "true" do - Routes.site_path(conn, :settings_integrations, conn.assigns.site.domain) + Routes.site_path(conn, :settings_integrations, site.domain) else - Routes.site_path(conn, :settings_imports_exports, conn.assigns.site.domain) + Routes.site_path(conn, :settings_imports_exports, site.domain) end - case Plausible.Google.UA.API.list_views(access_token) do - {:ok, view_ids} -> + result = + if legacy == "true" do + Plausible.Google.UA.API.list_views(access_token) + else + Plausible.Google.API.list_properties_and_views(access_token) + end + + case result do + {:ok, properties_and_views} -> conn |> assign(:skip_plausible_tracking, true) - |> render("view_id_form.html", + |> render("property_or_view_form.html", access_token: access_token, refresh_token: refresh_token, expires_at: expires_at, site: conn.assigns.site, - view_ids: view_ids, + properties_and_views: properties_and_views, legacy: legacy, layout: {PlausibleWeb.LayoutView, "focus.html"} ) @@ -74,62 +83,62 @@ defmodule PlausibleWeb.UniversalAnalyticsController do # see https://stackoverflow.com/a/57416769 @google_analytics_new_user_metric_date ~D[2016-08-24] - def view_id(conn, %{ - "view_id" => view_id, + + def property_or_view(conn, %{ + "property_or_view" => property_or_view, "access_token" => access_token, "refresh_token" => refresh_token, "expires_at" => expires_at, "legacy" => legacy }) do site = conn.assigns.site - start_date = Plausible.Google.UA.API.get_analytics_start_date(access_token, view_id) + start_date = Plausible.Google.API.get_analytics_start_date(access_token, property_or_view) case start_date do {:ok, nil} -> - {:ok, view_ids} = Plausible.Google.UA.API.list_views(access_token) + {:ok, properties_and_views} = + if legacy == "true" do + Plausible.Google.UA.API.list_views(access_token) + else + Plausible.Google.API.list_properties_and_views(access_token) + end conn |> assign(:skip_plausible_tracking, true) - |> render("view_id_form.html", + |> render("property_or_view_form.html", access_token: access_token, refresh_token: refresh_token, expires_at: expires_at, site: site, - view_ids: view_ids, - selected_view_id_error: "No data found. Nothing to import", + properties_and_views: properties_and_views, + selected_property_or_view_error: "No data found. Nothing to import", legacy: legacy, layout: {PlausibleWeb.LayoutView, "focus.html"} ) {:ok, date} -> - if Timex.before?(date, @google_analytics_new_user_metric_date) do - redirect(conn, - to: - Routes.universal_analytics_path(conn, :user_metric_notice, site.domain, - view_id: view_id, - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at, - legacy: legacy - ) - ) - else - redirect(conn, - to: - Routes.universal_analytics_path(conn, :confirm, site.domain, - view_id: view_id, - access_token: access_token, - refresh_token: refresh_token, - expires_at: expires_at, - legacy: legacy - ) - ) - end + action = + if Timex.before?(date, @google_analytics_new_user_metric_date) do + :user_metric_notice + else + :confirm + end + + redirect(conn, + to: + Routes.google_analytics_path(conn, action, site.domain, + property_or_view: property_or_view, + access_token: access_token, + refresh_token: refresh_token, + expires_at: expires_at, + legacy: legacy + ) + ) end end def confirm(conn, %{ - "view_id" => view_id, + "property_or_view" => property_or_view, "access_token" => access_token, "refresh_token" => refresh_token, "expires_at" => expires_at, @@ -137,11 +146,12 @@ defmodule PlausibleWeb.UniversalAnalyticsController do }) do site = conn.assigns.site - start_date = Plausible.Google.UA.API.get_analytics_start_date(access_token, view_id) + start_date = Plausible.Google.API.get_analytics_start_date(access_token, property_or_view) end_date = Plausible.Sites.native_stats_start_date(site) || Timex.today(site.timezone) - {:ok, {view_name, view_id}} = Plausible.Google.UA.API.get_view(access_token, view_id) + {:ok, %{name: property_or_view_name, id: property_or_view}} = + Plausible.Google.API.get_property_or_view(access_token, property_or_view) conn |> assign(:skip_plausible_tracking, true) @@ -150,17 +160,18 @@ defmodule PlausibleWeb.UniversalAnalyticsController do refresh_token: refresh_token, expires_at: expires_at, site: site, - selected_view_id: view_id, - selected_view_id_name: view_name, + selected_property_or_view: property_or_view, + selected_property_or_view_name: property_or_view_name, start_date: start_date, end_date: end_date, + property?: Plausible.Google.API.property?(property_or_view), legacy: legacy, layout: {PlausibleWeb.LayoutView, "focus.html"} ) end def import(conn, %{ - "view_id" => view_id, + "property_or_view" => property_or_view, "start_date" => start_date, "end_date" => end_date, "access_token" => access_token, @@ -178,11 +189,23 @@ defmodule PlausibleWeb.UniversalAnalyticsController do Routes.site_path(conn, :settings_imports_exports, site.domain) end - {:ok, _} = + if Plausible.Google.API.property?(property_or_view) do + {:ok, _} = + Plausible.Imported.GoogleAnalytics4.new_import( + site, + current_user, + property: property_or_view, + start_date: start_date, + end_date: end_date, + access_token: access_token, + refresh_token: refresh_token, + token_expires_at: expires_at + ) + else Plausible.Imported.UniversalAnalytics.new_import( site, current_user, - view_id: view_id, + view_id: property_or_view, start_date: start_date, end_date: end_date, access_token: access_token, @@ -190,6 +213,7 @@ defmodule PlausibleWeb.UniversalAnalyticsController do token_expires_at: expires_at, legacy: legacy == "true" ) + end conn |> put_flash(:success, "Import scheduled. An email will be sent when it completes.") diff --git a/lib/plausible_web/router.ex b/lib/plausible_web/router.ex index d7c0ff4147..6a4fd7660c 100644 --- a/lib/plausible_web/router.ex +++ b/lib/plausible_web/router.ex @@ -373,27 +373,20 @@ defmodule PlausibleWeb.Router do delete "/:website", SiteController, :delete_site delete "/:website/stats", SiteController, :reset_stats - get "/:website/import/google-analytics/view-id", - UniversalAnalyticsController, - :view_id_form + get "/:website/import/google-analytics/property-or-view", + GoogleAnalyticsController, + :property_or_view_form - post "/:website/import/google-analytics/view-id", UniversalAnalyticsController, :view_id + post "/:website/import/google-analytics/property-or-view", + GoogleAnalyticsController, + :property_or_view get "/:website/import/google-analytics/user-metric", - UniversalAnalyticsController, + GoogleAnalyticsController, :user_metric_notice - get "/:website/import/google-analytics/confirm", UniversalAnalyticsController, :confirm - post "/:website/settings/google-import", UniversalAnalyticsController, :import - - get "/:website/import/google-analytics4/property", - GoogleAnalytics4Controller, - :property_form - - post "/:website/import/google-analytics4/property", GoogleAnalytics4Controller, :property - - get "/:website/import/google-analytics4/confirm", GoogleAnalytics4Controller, :confirm - post "/:website/settings/google4-import", GoogleAnalytics4Controller, :import + get "/:website/import/google-analytics/confirm", GoogleAnalyticsController, :confirm + post "/:website/settings/google-import", GoogleAnalyticsController, :import delete "/:website/settings/forget-imported", SiteController, :forget_imported delete "/:website/settings/forget-import/:import_id", SiteController, :forget_import diff --git a/lib/plausible_web/templates/universal_analytics/confirm.html.heex b/lib/plausible_web/templates/google_analytics/confirm.html.heex similarity index 69% rename from lib/plausible_web/templates/universal_analytics/confirm.html.heex rename to lib/plausible_web/templates/google_analytics/confirm.html.heex index 3d6f143f32..8db55bdc46 100644 --- a/lib/plausible_web/templates/universal_analytics/confirm.html.heex +++ b/lib/plausible_web/templates/google_analytics/confirm.html.heex @@ -1,4 +1,4 @@ -<%= form_for @conn, Routes.universal_analytics_path(@conn, :import, @site.domain), [class: "max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %> +<%= form_for @conn, Routes.google_analytics_path(@conn, :import, @site.domain), [class: "max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %>
- The following error occurred when fetching your Google Analytics 4 data. -
-<%= error %>
- <% end %> - - <%= submit("Confirm import", class: "button mt-6") %> -<% end %> diff --git a/lib/plausible_web/templates/google_analytics4/property_form.html.heex b/lib/plausible_web/templates/google_analytics4/property_form.html.heex deleted file mode 100644 index c88461073c..0000000000 --- a/lib/plausible_web/templates/google_analytics4/property_form.html.heex +++ /dev/null @@ -1,19 +0,0 @@ -<%= form_for @conn, Routes.google_analytics4_path(@conn, :property, @site.domain), [class: "max-w-md w-full mx-auto bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"], fn f -> %> -