analytics/lib/workers/import_google_analytics.ex
Vini Brasil 1cb07efe6d
Save city name when importing from GA (#2608)
This commit adds city data to imported records from Google Analytics. The
current implementation sets city to 0 because GA does not use the GeoNames
database.

Google Analytics Reporting API uses [Geographical IDs](https://developers.google.com/analytics/devguides/collection/protocol/v1/geoid)
to identify cities and countries. Plausible uses
[GeoNames](https://geonames.org/) and I couldn't find databases corelating the
two.

Fortunately, GA also returns the city name and this commit uses the city name
and the country ISO code to find the Geoname ID. To avoid making expensive ETS
searches, I created another ETS table in the Location library that uses
{country, city} as a key.

Related PR: https://github.com/plausible/location/pull/3
2023-02-14 09:32:18 -03:00

72 lines
1.9 KiB
Elixir

defmodule Plausible.Workers.ImportGoogleAnalytics do
use Plausible.Repo
require Logger
use Oban.Worker,
queue: :google_analytics_imports,
max_attempts: 3,
unique: [fields: [:args], period: 60]
@impl Oban.Worker
def perform(
%Oban.Job{
args:
%{
"site_id" => site_id,
"view_id" => view_id,
"start_date" => start_date,
"end_date" => end_date
} = args
},
google_api \\ Plausible.Google.Api
) do
site = Repo.get(Plausible.Site, site_id) |> Repo.preload([[memberships: :user]])
start_date = Date.from_iso8601!(start_date)
end_date = Date.from_iso8601!(end_date)
date_range = Date.range(start_date, end_date)
auth = {args["access_token"], args["refresh_token"], args["token_expires_at"]}
case google_api.import_analytics(site, date_range, view_id, auth) do
:ok ->
Plausible.Site.import_success(site)
|> Repo.update!()
Enum.each(site.memberships, fn membership ->
if membership.role in [:owner, :admin] do
PlausibleWeb.Email.import_success(membership.user, site)
|> Plausible.Mailer.send()
end
end)
:ok
{:error, error} ->
Logger.error("Import: Failed to import from GA. Reason: #{inspect(error)}")
import_failed(site)
{:error, error}
end
end
@impl Oban.Worker
def backoff(_job) do
# 5 minutes
300
end
def import_failed(site) do
site = Repo.preload(site, memberships: :user)
Plausible.Site.import_failure(site) |> Repo.update!()
Plausible.Purge.delete_imported_stats!(site)
Enum.each(site.memberships, fn membership ->
if membership.role in [:owner, :admin] do
PlausibleWeb.Email.import_failure(membership.user, site)
|> Plausible.Mailer.send()
end
end)
end
end