diff --git a/lib/plausible/clickhouse_event_v2.ex b/lib/plausible/clickhouse_event_v2.ex index fbbeb1712..017d57639 100644 --- a/lib/plausible/clickhouse_event_v2.ex +++ b/lib/plausible/clickhouse_event_v2.ex @@ -26,6 +26,7 @@ defmodule Plausible.ClickhouseEventV2 do # Session attributes field :referrer, :string field :referrer_source, :string + field :channel, Ch, type: "LowCardinality(String)" field :utm_medium, :string field :utm_source, :string field :utm_campaign, :string @@ -70,6 +71,7 @@ defmodule Plausible.ClickhouseEventV2 do :session_id, :referrer, :referrer_source, + :channel, :utm_medium, :utm_source, :utm_campaign, diff --git a/lib/plausible/clickhouse_session_v2.ex b/lib/plausible/clickhouse_session_v2.ex index 2c4c7a725..edfbc233c 100644 --- a/lib/plausible/clickhouse_session_v2.ex +++ b/lib/plausible/clickhouse_session_v2.ex @@ -58,6 +58,7 @@ defmodule Plausible.ClickhouseSessionV2 do field :utm_term, :string field :referrer, :string field :referrer_source, :string + field :channel, Ch, type: "LowCardinality(String)" field :country_code, Ch, type: "LowCardinality(FixedString(2))" field :subdivision1_code, Ch, type: "LowCardinality(String)" diff --git a/lib/plausible/ingestion/acquisition.ex b/lib/plausible/ingestion/acquisition.ex index 510e9966c..d6024bf0e 100644 --- a/lib/plausible/ingestion/acquisition.ex +++ b/lib/plausible/ingestion/acquisition.ex @@ -1,5 +1,11 @@ defmodule Plausible.Ingestion.Acquisition do @moduledoc false + @external_resource "priv/ga4-source-categories.csv" + @source_categories Application.app_dir(:plausible, "priv/ga4-source-categories.csv") + |> File.read!() + |> NimbleCSV.RFC4180.parse_string(skip_headers: false) + |> Enum.map(fn [source, category] -> {source, category} end) + |> Enum.into(%{}) def init() do :ets.new(__MODULE__, [ @@ -24,4 +30,149 @@ defmodule Plausible.Ingestion.Acquisition do _ -> source end end + + def get_channel(request, source) do + cond do + cross_network?(request) -> "Cross-network" + paid_shopping?(request, source) -> "Paid Shopping" + paid_search?(request, source) -> "Paid Search" + paid_social?(request, source) -> "Paid Social" + paid_video?(request, source) -> "Paid Video" + display?(request) -> "Display" + paid_other?(request) -> "Paid Other" + organic_shopping?(request, source) -> "Organic Shopping" + organic_social?(request, source) -> "Organic Social" + organic_video?(request, source) -> "Organic Video" + search_source?(source) -> "Organic Search" + email?(request) -> "Email" + affiliates?(request) -> "Affiliates" + audio?(request) -> "Audio" + sms?(request) -> "SMS" + mobile_push_notifications?(request, source) -> "Mobile Push Notifications" + referral?(request, source) -> "Referral" + true -> "Direct" + end + end + + defp cross_network?(request) do + String.contains?(request.query_params["utm_campaign"] || "", "cross-network") + end + + defp paid_shopping?(request, source) do + (shopping_source?(source) or shopping_campaign?(request.query_params["utm_campaign"])) and + paid_medium?(request.query_params["utm_medium"]) + end + + defp paid_search?(request, source) do + (search_source?(source) and paid_medium?(request.query_params["utm_medium"])) or + (source == "Google" and !!request.query_params["gclid"]) or + (source == "Bing" and !!request.query_params["msclkid"]) + end + + defp paid_social?(request, source) do + social_source?(source) and paid_medium?(request.query_params["utm_medium"]) + end + + defp paid_video?(request, source) do + video_source?(source) and paid_medium?(request.query_params["utm_medium"]) + end + + defp display?(request) do + request.query_params["utm_medium"] in [ + "display", + "banner", + "expandable", + "interstitial", + "cpm" + ] + end + + defp paid_other?(request) do + paid_medium?(request.query_params["utm_medium"]) + end + + defp organic_shopping?(request, source) do + shopping_source?(source) or shopping_campaign?(request.query_params["utm_campaign"]) + end + + defp organic_social?(request, source) do + social_source?(source) or + request.query_params["utm_medium"] in [ + "social", + "social-network", + "social-media", + "sm", + "social network", + "social media" + ] + end + + defp organic_video?(request, source) do + video_source?(source) or String.contains?(request.query_params["utm_medium"] || "", "video") + end + + defp referral?(request, source) do + request.query_params["utm_medium"] in ["referral", "app", "link"] or + !!source + end + + @email_tags ["email", "e-mail", "e_mail", "e mail"] + defp email?(request) do + String.contains?(request.query_params["utm_source"] || "", @email_tags) or + String.contains?(request.query_params["utm_medium"] || "", @email_tags) + end + + defp affiliates?(request) do + request.query_params["utm_medium"] == "affiliate" + end + + defp audio?(request) do + request.query_params["utm_medium"] == "audio" + end + + defp sms?(request) do + request.query_params["utm_source"] == "sms" or + request.query_params["utm_medium"] == "sms" + end + + defp mobile_push_notifications?(request, source) do + medium = request.query_params["utm_medium"] || "" + + String.ends_with?(medium, "push") or + String.contains?(medium, ["mobile", "notification"]) or + source == "firebase" + end + + # # Helper functions for source and medium checks + defp shopping_source?(nil), do: false + + defp shopping_source?(source) do + @source_categories[String.downcase(source)] == "SOURCE_CATEGORY_SHOPPING" + end + + defp shopping_campaign?(campaign_name) do + Regex.match?(~r/^(.*(([^a-df-z]|^)shop|shopping).*)$/, campaign_name || "") + end + + defp search_source?(nil), do: false + + defp search_source?(source) do + @source_categories[String.downcase(source)] == "SOURCE_CATEGORY_SEARCH" + end + + defp social_source?(nil), do: false + + defp social_source?(source) do + @source_categories[String.downcase(source)] == "SOURCE_CATEGORY_SOCIAL" + end + + defp video_source?(nil), do: false + + defp video_source?(source) do + @source_categories[String.downcase(source)] == "SOURCE_CATEGORY_VIDEO" + end + + defp paid_medium?(medium) do + Regex.match?(~r/^(.*cp.*|ppc|retargeting|paid.*)$/, medium || "") + end end diff --git a/lib/plausible/ingestion/event.ex b/lib/plausible/ingestion/event.ex index 089ca7e45..3f8230c9f 100644 --- a/lib/plausible/ingestion/event.ex +++ b/lib/plausible/ingestion/event.ex @@ -250,9 +250,12 @@ defmodule Plausible.Ingestion.Event do defp put_referrer(%__MODULE__{} = event) do ref = parse_referrer(event.request.uri, event.request.referrer) + source = get_referrer_source(event.request, ref) + channel = Plausible.Ingestion.Acquisition.get_channel(event.request, source) update_session_attrs(event, %{ - referrer_source: get_referrer_source(event.request, ref), + channel: channel, + referrer_source: source, referrer: clean_referrer(ref) }) end diff --git a/lib/plausible/session/cache_store.ex b/lib/plausible/session/cache_store.ex index 51bbe858a..e446bfd7b 100644 --- a/lib/plausible/session/cache_store.ex +++ b/lib/plausible/session/cache_store.ex @@ -95,6 +95,7 @@ defmodule Plausible.Session.CacheStore do pageviews: if(event.name == "pageview", do: 1, else: 0), events: 1, referrer: Map.get(session_attributes, :referrer), + channel: Map.get(session_attributes, :channel), referrer_source: Map.get(session_attributes, :referrer_source), utm_medium: Map.get(session_attributes, :utm_medium), utm_source: Map.get(session_attributes, :utm_source), diff --git a/priv/ga4-source-categories.csv b/priv/ga4-source-categories.csv new file mode 100644 index 000000000..be40ba154 --- /dev/null +++ b/priv/ga4-source-categories.csv @@ -0,0 +1,820 @@ +source,source category +360.cn,SOURCE_CATEGORY_SEARCH +43things,SOURCE_CATEGORY_SOCIAL +43things.com,SOURCE_CATEGORY_SOCIAL +51.com,SOURCE_CATEGORY_SOCIAL +5ch.net,SOURCE_CATEGORY_SOCIAL +Google Shopping,SOURCE_CATEGORY_SHOPPING +Hatena,SOURCE_CATEGORY_SOCIAL +IGShopping,SOURCE_CATEGORY_SHOPPING +ImageShack,SOURCE_CATEGORY_SOCIAL +aax-us-east.amazon-adsystem.com,SOURCE_CATEGORY_SHOPPING +aax.amazon-adsystem.com,SOURCE_CATEGORY_SHOPPING +academia.edu,SOURCE_CATEGORY_SOCIAL +activerain,SOURCE_CATEGORY_SOCIAL +activerain.com,SOURCE_CATEGORY_SOCIAL +activeworlds,SOURCE_CATEGORY_SOCIAL +activeworlds.com,SOURCE_CATEGORY_SOCIAL +addthis,SOURCE_CATEGORY_SOCIAL +addthis.com,SOURCE_CATEGORY_SOCIAL +airg.ca,SOURCE_CATEGORY_SOCIAL +alibaba,SOURCE_CATEGORY_SHOPPING +alibaba.com,SOURCE_CATEGORY_SHOPPING +alice,SOURCE_CATEGORY_SEARCH +allnurses.com,SOURCE_CATEGORY_SOCIAL +allrecipes.com,SOURCE_CATEGORY_SOCIAL +alumniclass,SOURCE_CATEGORY_SOCIAL +alumniclass.com,SOURCE_CATEGORY_SOCIAL +amazon,SOURCE_CATEGORY_SHOPPING +amazon.co.uk,SOURCE_CATEGORY_SHOPPING +amazon.com,SOURCE_CATEGORY_SHOPPING +ameba.jp,SOURCE_CATEGORY_SOCIAL +ameblo.jp,SOURCE_CATEGORY_SOCIAL +americantowns,SOURCE_CATEGORY_SOCIAL +americantowns.com,SOURCE_CATEGORY_SOCIAL +amp.reddit.com,SOURCE_CATEGORY_SOCIAL +ancestry.com,SOURCE_CATEGORY_SOCIAL +anobii,SOURCE_CATEGORY_SOCIAL +anobii.com,SOURCE_CATEGORY_SOCIAL +answerbag,SOURCE_CATEGORY_SOCIAL +answerbag.com,SOURCE_CATEGORY_SOCIAL +answers.yahoo.com,SOURCE_CATEGORY_SOCIAL +aol,SOURCE_CATEGORY_SEARCH +aolanswers,SOURCE_CATEGORY_SOCIAL +aolanswers.com,SOURCE_CATEGORY_SOCIAL +apps.facebook.com,SOURCE_CATEGORY_SOCIAL +apps.shopify.com,SOURCE_CATEGORY_SHOPPING +ar.pinterest.com,SOURCE_CATEGORY_SOCIAL +ar.search.yahoo.com,SOURCE_CATEGORY_SEARCH +artstation.com,SOURCE_CATEGORY_SOCIAL +ask,SOURCE_CATEGORY_SEARCH +askubuntu,SOURCE_CATEGORY_SOCIAL +askubuntu.com,SOURCE_CATEGORY_SOCIAL +asmallworld.com,SOURCE_CATEGORY_SOCIAL +at.search.yahoo.com,SOURCE_CATEGORY_SEARCH +athlinks,SOURCE_CATEGORY_SOCIAL +athlinks.com,SOURCE_CATEGORY_SOCIAL +au.search.yahoo.com,SOURCE_CATEGORY_SEARCH +auone,SOURCE_CATEGORY_SEARCH +avg,SOURCE_CATEGORY_SEARCH +away.vk.com,SOURCE_CATEGORY_SOCIAL +awe.sm,SOURCE_CATEGORY_SOCIAL +b.hatena.ne.jp,SOURCE_CATEGORY_SOCIAL +baby-gaga,SOURCE_CATEGORY_SOCIAL +baby-gaga.com,SOURCE_CATEGORY_SOCIAL +babyblog.ru,SOURCE_CATEGORY_SOCIAL +babylon,SOURCE_CATEGORY_SEARCH +badoo,SOURCE_CATEGORY_SOCIAL +badoo.com,SOURCE_CATEGORY_SOCIAL +baidu,SOURCE_CATEGORY_SEARCH +bebo,SOURCE_CATEGORY_SOCIAL +bebo.com,SOURCE_CATEGORY_SOCIAL +beforeitsnews,SOURCE_CATEGORY_SOCIAL +beforeitsnews.com,SOURCE_CATEGORY_SOCIAL +bharatstudent,SOURCE_CATEGORY_SOCIAL +bharatstudent.com,SOURCE_CATEGORY_SOCIAL +biglobe,SOURCE_CATEGORY_SEARCH +biglobe.co.jp,SOURCE_CATEGORY_SEARCH +biglobe.ne.jp,SOURCE_CATEGORY_SEARCH +biip.no,SOURCE_CATEGORY_SOCIAL +bing,SOURCE_CATEGORY_SEARCH +biswap.org,SOURCE_CATEGORY_SOCIAL +bit.ly,SOURCE_CATEGORY_SOCIAL +blackcareernetwork.com,SOURCE_CATEGORY_SOCIAL +blackplanet,SOURCE_CATEGORY_SOCIAL +blackplanet.com,SOURCE_CATEGORY_SOCIAL +blip.fm,SOURCE_CATEGORY_SOCIAL +blog.com,SOURCE_CATEGORY_SOCIAL +blog.feedspot.com,SOURCE_CATEGORY_SOCIAL +blog.goo.ne.jp,SOURCE_CATEGORY_SOCIAL +blog.naver.com,SOURCE_CATEGORY_SOCIAL +blog.twitch.tv,SOURCE_CATEGORY_VIDEO +blog.yahoo.co.jp,SOURCE_CATEGORY_SOCIAL +blogg.no,SOURCE_CATEGORY_SOCIAL +bloggang.com,SOURCE_CATEGORY_SOCIAL +blogger,SOURCE_CATEGORY_SOCIAL +blogger.com,SOURCE_CATEGORY_SOCIAL +blogher,SOURCE_CATEGORY_SOCIAL +blogher.com,SOURCE_CATEGORY_SOCIAL +bloglines,SOURCE_CATEGORY_SOCIAL +bloglines.com,SOURCE_CATEGORY_SOCIAL +blogs.com,SOURCE_CATEGORY_SOCIAL +blogsome,SOURCE_CATEGORY_SOCIAL +blogsome.com,SOURCE_CATEGORY_SOCIAL +blogspot,SOURCE_CATEGORY_SOCIAL +blogspot.com,SOURCE_CATEGORY_SOCIAL +blogster,SOURCE_CATEGORY_SOCIAL +blogster.com,SOURCE_CATEGORY_SOCIAL +blurtit,SOURCE_CATEGORY_SOCIAL +blurtit.com,SOURCE_CATEGORY_SOCIAL +bookmarks.yahoo.co.jp,SOURCE_CATEGORY_SOCIAL +bookmarks.yahoo.com,SOURCE_CATEGORY_SOCIAL +br.pinterest.com,SOURCE_CATEGORY_SOCIAL +br.search.yahoo.com,SOURCE_CATEGORY_SEARCH +brightkite,SOURCE_CATEGORY_SOCIAL +brightkite.com,SOURCE_CATEGORY_SOCIAL +brizzly,SOURCE_CATEGORY_SOCIAL +brizzly.com,SOURCE_CATEGORY_SOCIAL +business.facebook.com,SOURCE_CATEGORY_SOCIAL +buzzfeed,SOURCE_CATEGORY_SOCIAL +buzzfeed.com,SOURCE_CATEGORY_SOCIAL +buzznet,SOURCE_CATEGORY_SOCIAL +buzznet.com,SOURCE_CATEGORY_SOCIAL +ca.search.yahoo.com,SOURCE_CATEGORY_SEARCH +cafe.naver.com,SOURCE_CATEGORY_SOCIAL +cafemom,SOURCE_CATEGORY_SOCIAL +cafemom.com,SOURCE_CATEGORY_SOCIAL +camospace,SOURCE_CATEGORY_SOCIAL +camospace.com,SOURCE_CATEGORY_SOCIAL +canalblog.com,SOURCE_CATEGORY_SOCIAL +care.com,SOURCE_CATEGORY_SOCIAL +care2,SOURCE_CATEGORY_SOCIAL +care2.com,SOURCE_CATEGORY_SOCIAL +caringbridge.org,SOURCE_CATEGORY_SOCIAL +catster,SOURCE_CATEGORY_SOCIAL +catster.com,SOURCE_CATEGORY_SOCIAL +cbnt.io,SOURCE_CATEGORY_SOCIAL +cellufun,SOURCE_CATEGORY_SOCIAL +cellufun.com,SOURCE_CATEGORY_SOCIAL +centerblog.net,SOURCE_CATEGORY_SOCIAL +centrum.cz,SOURCE_CATEGORY_SEARCH +ch.search.yahoo.com,SOURCE_CATEGORY_SEARCH +chat.zalo.me,SOURCE_CATEGORY_SOCIAL +checkout.shopify.com,SOURCE_CATEGORY_SHOPPING +checkout.stripe.com,SOURCE_CATEGORY_SHOPPING +chegg.com,SOURCE_CATEGORY_SOCIAL +chicagonow,SOURCE_CATEGORY_SOCIAL +chicagonow.com,SOURCE_CATEGORY_SOCIAL +chiebukuro.yahoo.co.jp,SOURCE_CATEGORY_SOCIAL +cl.search.yahoo.com,SOURCE_CATEGORY_SEARCH +classmates,SOURCE_CATEGORY_SOCIAL +classmates.com,SOURCE_CATEGORY_SOCIAL +classquest,SOURCE_CATEGORY_SOCIAL +classquest.com,SOURCE_CATEGORY_SOCIAL +cn.bing.com,SOURCE_CATEGORY_SEARCH +cnn,SOURCE_CATEGORY_SEARCH +co.pinterest.com,SOURCE_CATEGORY_SOCIAL +co.search.yahoo.com,SOURCE_CATEGORY_SEARCH +cocolog-nifty,SOURCE_CATEGORY_SOCIAL +cocolog-nifty.com,SOURCE_CATEGORY_SOCIAL +comcast,SOURCE_CATEGORY_SEARCH +conduit,SOURCE_CATEGORY_SEARCH +copainsdavant.linternaute.com,SOURCE_CATEGORY_SOCIAL +couchsurfing.org,SOURCE_CATEGORY_SOCIAL +cozycot,SOURCE_CATEGORY_SOCIAL +cozycot.com,SOURCE_CATEGORY_SOCIAL +cr.shopping.naver.com,SOURCE_CATEGORY_SHOPPING +cr2.shopping.naver.com,SOURCE_CATEGORY_SHOPPING +crackle,SOURCE_CATEGORY_VIDEO +crackle.com,SOURCE_CATEGORY_VIDEO +cross.tv,SOURCE_CATEGORY_SOCIAL +crunchyroll,SOURCE_CATEGORY_SOCIAL +crunchyroll.com,SOURCE_CATEGORY_SOCIAL +curiositystream,SOURCE_CATEGORY_VIDEO +curiositystream.com,SOURCE_CATEGORY_VIDEO +cyworld,SOURCE_CATEGORY_SOCIAL +cyworld.com,SOURCE_CATEGORY_SOCIAL +cz.pinterest.com,SOURCE_CATEGORY_SOCIAL +d.hatena.ne.jp,SOURCE_CATEGORY_SOCIAL +d.tube,SOURCE_CATEGORY_VIDEO +dailymotion,SOURCE_CATEGORY_VIDEO +dailymotion.com,SOURCE_CATEGORY_VIDEO +dailystrength.org,SOURCE_CATEGORY_SOCIAL +dashboard.twitch.tv,SOURCE_CATEGORY_VIDEO +daum,SOURCE_CATEGORY_SEARCH +daum.net,SOURCE_CATEGORY_SEARCH +de.search.yahoo.com,SOURCE_CATEGORY_SEARCH +deluxe.com,SOURCE_CATEGORY_SOCIAL +deviantart,SOURCE_CATEGORY_SOCIAL +deviantart.com,SOURCE_CATEGORY_SOCIAL +dianping,SOURCE_CATEGORY_SOCIAL +dianping.com,SOURCE_CATEGORY_SOCIAL +digg,SOURCE_CATEGORY_SOCIAL +digg.com,SOURCE_CATEGORY_SOCIAL +diigo,SOURCE_CATEGORY_SOCIAL +diigo.com,SOURCE_CATEGORY_SOCIAL +discover.hubpages.com,SOURCE_CATEGORY_SOCIAL +disneyplus,SOURCE_CATEGORY_VIDEO +disneyplus.com,SOURCE_CATEGORY_VIDEO +disqus,SOURCE_CATEGORY_SOCIAL +disqus.com,SOURCE_CATEGORY_SOCIAL +dk.search.yahoo.com,SOURCE_CATEGORY_SEARCH +dogpile,SOURCE_CATEGORY_SEARCH +dogpile.com,SOURCE_CATEGORY_SEARCH +dogster,SOURCE_CATEGORY_SOCIAL +dogster.com,SOURCE_CATEGORY_SOCIAL +dol2day,SOURCE_CATEGORY_SOCIAL +dol2day.com,SOURCE_CATEGORY_SOCIAL +doostang,SOURCE_CATEGORY_SOCIAL +doostang.com,SOURCE_CATEGORY_SOCIAL +dopplr,SOURCE_CATEGORY_SOCIAL +dopplr.com,SOURCE_CATEGORY_SOCIAL +douban,SOURCE_CATEGORY_SOCIAL +douban.com,SOURCE_CATEGORY_SOCIAL +draft.blogger.com,SOURCE_CATEGORY_SOCIAL +draugiem.lv,SOURCE_CATEGORY_SOCIAL +drugs-forum,SOURCE_CATEGORY_SOCIAL +drugs-forum.com,SOURCE_CATEGORY_SOCIAL +duckduckgo,SOURCE_CATEGORY_SEARCH +dzone,SOURCE_CATEGORY_SOCIAL +dzone.com,SOURCE_CATEGORY_SOCIAL +ebay,SOURCE_CATEGORY_SHOPPING +ebay.co.uk,SOURCE_CATEGORY_SHOPPING +ebay.com,SOURCE_CATEGORY_SHOPPING +ebay.com.au,SOURCE_CATEGORY_SHOPPING +ebay.de,SOURCE_CATEGORY_SHOPPING +ecosia.org,SOURCE_CATEGORY_SEARCH +edublogs.org,SOURCE_CATEGORY_SOCIAL +elftown,SOURCE_CATEGORY_SOCIAL +elftown.com,SOURCE_CATEGORY_SOCIAL +email.seznam.cz,SOURCE_CATEGORY_SEARCH +eniro,SOURCE_CATEGORY_SEARCH +epicurious.com,SOURCE_CATEGORY_SOCIAL +es.search.yahoo.com,SOURCE_CATEGORY_SEARCH +espanol.search.yahoo.com,SOURCE_CATEGORY_SEARCH +etsy,SOURCE_CATEGORY_SHOPPING +etsy.com,SOURCE_CATEGORY_SHOPPING +everforo.com,SOURCE_CATEGORY_SOCIAL +exalead.com,SOURCE_CATEGORY_SEARCH +exblog.jp,SOURCE_CATEGORY_SOCIAL +excite.com,SOURCE_CATEGORY_SEARCH +extole,SOURCE_CATEGORY_SOCIAL +extole.com,SOURCE_CATEGORY_SOCIAL +facebook,SOURCE_CATEGORY_SOCIAL +facebook.com,SOURCE_CATEGORY_SOCIAL +faceparty,SOURCE_CATEGORY_SOCIAL +faceparty.com,SOURCE_CATEGORY_SOCIAL +fandom.com,SOURCE_CATEGORY_SOCIAL +fanpop,SOURCE_CATEGORY_SOCIAL +fanpop.com,SOURCE_CATEGORY_SOCIAL +fark,SOURCE_CATEGORY_SOCIAL +fark.com,SOURCE_CATEGORY_SOCIAL +fast.wistia.net,SOURCE_CATEGORY_VIDEO +fb,SOURCE_CATEGORY_SOCIAL +fb.me,SOURCE_CATEGORY_SOCIAL +fc2,SOURCE_CATEGORY_SOCIAL +fc2.com,SOURCE_CATEGORY_SOCIAL +feedspot,SOURCE_CATEGORY_SOCIAL +feministing,SOURCE_CATEGORY_SOCIAL +feministing.com,SOURCE_CATEGORY_SOCIAL +fi.search.yahoo.com,SOURCE_CATEGORY_SEARCH +filmaffinity,SOURCE_CATEGORY_SOCIAL +filmaffinity.com,SOURCE_CATEGORY_SOCIAL +firmy.cz,SOURCE_CATEGORY_SEARCH +flickr,SOURCE_CATEGORY_SOCIAL +flickr.com,SOURCE_CATEGORY_SOCIAL +flipboard,SOURCE_CATEGORY_SOCIAL +flipboard.com,SOURCE_CATEGORY_SOCIAL +folkdirect,SOURCE_CATEGORY_SOCIAL +folkdirect.com,SOURCE_CATEGORY_SOCIAL +foodservice,SOURCE_CATEGORY_SOCIAL +foodservice.com,SOURCE_CATEGORY_SOCIAL +forums.androidcentral.com,SOURCE_CATEGORY_SOCIAL +forums.crackberry.com,SOURCE_CATEGORY_SOCIAL +forums.imore.com,SOURCE_CATEGORY_SOCIAL +forums.nexopia.com,SOURCE_CATEGORY_SOCIAL +forums.webosnation.com,SOURCE_CATEGORY_SOCIAL +forums.wpcentral.com,SOURCE_CATEGORY_SOCIAL +fotki,SOURCE_CATEGORY_SOCIAL +fotki.com,SOURCE_CATEGORY_SOCIAL +fotolog,SOURCE_CATEGORY_SOCIAL +fotolog.com,SOURCE_CATEGORY_SOCIAL +foursquare,SOURCE_CATEGORY_SOCIAL +foursquare.com,SOURCE_CATEGORY_SOCIAL +fr.search.yahoo.com,SOURCE_CATEGORY_SEARCH +free.facebook.com,SOURCE_CATEGORY_SOCIAL +friendfeed,SOURCE_CATEGORY_SOCIAL +friendfeed.com,SOURCE_CATEGORY_SOCIAL +fruehstueckstreff.org,SOURCE_CATEGORY_SOCIAL +fubar,SOURCE_CATEGORY_SOCIAL +fubar.com,SOURCE_CATEGORY_SOCIAL +gaiaonline,SOURCE_CATEGORY_SOCIAL +gaiaonline.com,SOURCE_CATEGORY_SOCIAL +gamerdna,SOURCE_CATEGORY_SOCIAL +gamerdna.com,SOURCE_CATEGORY_SOCIAL +gather.com,SOURCE_CATEGORY_SOCIAL +geni.com,SOURCE_CATEGORY_SOCIAL +getpocket.com,SOURCE_CATEGORY_SOCIAL +glassboard,SOURCE_CATEGORY_SOCIAL +glassboard.com,SOURCE_CATEGORY_SOCIAL +glassdoor,SOURCE_CATEGORY_SOCIAL +glassdoor.com,SOURCE_CATEGORY_SOCIAL +globo,SOURCE_CATEGORY_SEARCH +go.mail.ru,SOURCE_CATEGORY_SEARCH +godtube,SOURCE_CATEGORY_SOCIAL +godtube.com,SOURCE_CATEGORY_SOCIAL +goldenline.pl,SOURCE_CATEGORY_SOCIAL +goldstar,SOURCE_CATEGORY_SOCIAL +goldstar.com,SOURCE_CATEGORY_SOCIAL +goo.gl,SOURCE_CATEGORY_SOCIAL +gooblog,SOURCE_CATEGORY_SOCIAL +goodreads,SOURCE_CATEGORY_SOCIAL +goodreads.com,SOURCE_CATEGORY_SOCIAL +google,SOURCE_CATEGORY_SEARCH +google+,SOURCE_CATEGORY_SOCIAL +google-play,SOURCE_CATEGORY_SEARCH +googlegroups.com,SOURCE_CATEGORY_SOCIAL +googleplus,SOURCE_CATEGORY_SOCIAL +govloop,SOURCE_CATEGORY_SOCIAL +govloop.com,SOURCE_CATEGORY_SOCIAL +gowalla,SOURCE_CATEGORY_SOCIAL +gowalla.com,SOURCE_CATEGORY_SOCIAL +gree.jp,SOURCE_CATEGORY_SOCIAL +groups.google.com,SOURCE_CATEGORY_SOCIAL +gulli.com,SOURCE_CATEGORY_SOCIAL +gutefrage.net,SOURCE_CATEGORY_SOCIAL +habbo,SOURCE_CATEGORY_SOCIAL +habbo.com,SOURCE_CATEGORY_SOCIAL +help.hulu.com,SOURCE_CATEGORY_VIDEO +help.netflix.com,SOURCE_CATEGORY_VIDEO +hi5,SOURCE_CATEGORY_SOCIAL +hi5.com,SOURCE_CATEGORY_SOCIAL +hk.search.yahoo.com,SOURCE_CATEGORY_SEARCH +hootsuite,SOURCE_CATEGORY_SOCIAL +hootsuite.com,SOURCE_CATEGORY_SOCIAL +houzz,SOURCE_CATEGORY_SOCIAL +houzz.com,SOURCE_CATEGORY_SOCIAL +hoverspot,SOURCE_CATEGORY_SOCIAL +hoverspot.com,SOURCE_CATEGORY_SOCIAL +hr.com,SOURCE_CATEGORY_SOCIAL +hu.pinterest.com,SOURCE_CATEGORY_SOCIAL +hubculture,SOURCE_CATEGORY_SOCIAL +hubculture.com,SOURCE_CATEGORY_SOCIAL +hubpages.com,SOURCE_CATEGORY_SOCIAL +hulu,SOURCE_CATEGORY_VIDEO +hulu.com,SOURCE_CATEGORY_VIDEO +hyves.net,SOURCE_CATEGORY_SOCIAL +hyves.nl,SOURCE_CATEGORY_SOCIAL +ibibo,SOURCE_CATEGORY_SOCIAL +ibibo.com,SOURCE_CATEGORY_SOCIAL +id.pinterest.com,SOURCE_CATEGORY_SOCIAL +id.search.yahoo.com,SOURCE_CATEGORY_SEARCH +id.twitch.tv,SOURCE_CATEGORY_VIDEO +identi.ca,SOURCE_CATEGORY_SOCIAL +ig,SOURCE_CATEGORY_SOCIAL +imageshack.com,SOURCE_CATEGORY_SOCIAL +imageshack.us,SOURCE_CATEGORY_SOCIAL +imvu,SOURCE_CATEGORY_SOCIAL +imvu.com,SOURCE_CATEGORY_SOCIAL +in.pinterest.com,SOURCE_CATEGORY_SOCIAL +in.search.yahoo.com,SOURCE_CATEGORY_SEARCH +incredimail,SOURCE_CATEGORY_SEARCH +insanejournal,SOURCE_CATEGORY_SOCIAL +insanejournal.com,SOURCE_CATEGORY_SOCIAL +instagram,SOURCE_CATEGORY_SOCIAL +instagram.com,SOURCE_CATEGORY_SOCIAL +instapaper,SOURCE_CATEGORY_SOCIAL +instapaper.com,SOURCE_CATEGORY_SOCIAL +internations.org,SOURCE_CATEGORY_SOCIAL +interpals.net,SOURCE_CATEGORY_SOCIAL +intherooms,SOURCE_CATEGORY_SOCIAL +intherooms.com,SOURCE_CATEGORY_SOCIAL +iq.com,SOURCE_CATEGORY_VIDEO +iqiyi,SOURCE_CATEGORY_VIDEO +iqiyi.com,SOURCE_CATEGORY_VIDEO +irc-galleria.net,SOURCE_CATEGORY_SOCIAL +is.gd,SOURCE_CATEGORY_SOCIAL +it.search.yahoo.com,SOURCE_CATEGORY_SEARCH +italki,SOURCE_CATEGORY_SOCIAL +italki.com,SOURCE_CATEGORY_SOCIAL +jammerdirect,SOURCE_CATEGORY_SOCIAL +jammerdirect.com,SOURCE_CATEGORY_SOCIAL +jappy.com,SOURCE_CATEGORY_SOCIAL +jappy.de,SOURCE_CATEGORY_SOCIAL +jobs.netflix.com,SOURCE_CATEGORY_VIDEO +justin.tv,SOURCE_CATEGORY_VIDEO +kaboodle.com,SOURCE_CATEGORY_SOCIAL +kakao,SOURCE_CATEGORY_SOCIAL +kakao.com,SOURCE_CATEGORY_SOCIAL +kakaocorp.com,SOURCE_CATEGORY_SOCIAL +kaneva,SOURCE_CATEGORY_SOCIAL +kaneva.com,SOURCE_CATEGORY_SOCIAL +kin.naver.com,SOURCE_CATEGORY_SOCIAL +kvasir,SOURCE_CATEGORY_SEARCH +l.facebook.com,SOURCE_CATEGORY_SOCIAL +l.instagram.com,SOURCE_CATEGORY_SOCIAL +l.messenger.com,SOURCE_CATEGORY_SOCIAL +last.fm,SOURCE_CATEGORY_SOCIAL +lens.google.com,SOURCE_CATEGORY_SEARCH +librarything,SOURCE_CATEGORY_SOCIAL +librarything.com,SOURCE_CATEGORY_SOCIAL +lifestream.aol.com,SOURCE_CATEGORY_SOCIAL +line,SOURCE_CATEGORY_SOCIAL +line.me,SOURCE_CATEGORY_SOCIAL +linkedin,SOURCE_CATEGORY_SOCIAL +linkedin.com,SOURCE_CATEGORY_SOCIAL +listal,SOURCE_CATEGORY_SOCIAL +listal.com,SOURCE_CATEGORY_SOCIAL +listography,SOURCE_CATEGORY_SOCIAL +listography.com,SOURCE_CATEGORY_SOCIAL +lite.qwant.com,SOURCE_CATEGORY_SEARCH +livedoor.com,SOURCE_CATEGORY_SOCIAL +livedoorblog,SOURCE_CATEGORY_SOCIAL +livejournal,SOURCE_CATEGORY_SOCIAL +livejournal.com,SOURCE_CATEGORY_SOCIAL +lm.facebook.com,SOURCE_CATEGORY_SOCIAL +lnkd.in,SOURCE_CATEGORY_SOCIAL +lycos,SOURCE_CATEGORY_SEARCH +m.alibaba.com,SOURCE_CATEGORY_SHOPPING +m.baidu.com,SOURCE_CATEGORY_SEARCH +m.blog.naver.com,SOURCE_CATEGORY_SOCIAL +m.cafe.naver.com,SOURCE_CATEGORY_SOCIAL +m.facebook.com,SOURCE_CATEGORY_SOCIAL +m.kin.naver.com,SOURCE_CATEGORY_SOCIAL +m.naver.com,SOURCE_CATEGORY_SEARCH +m.search.naver.com,SOURCE_CATEGORY_SEARCH +m.shopping.naver.com,SOURCE_CATEGORY_SHOPPING +m.sogou.com,SOURCE_CATEGORY_SEARCH +m.twitch.tv,SOURCE_CATEGORY_VIDEO +m.vk.com,SOURCE_CATEGORY_SOCIAL +m.yelp.com,SOURCE_CATEGORY_SOCIAL +m.youtube.com,SOURCE_CATEGORY_VIDEO +mail.rambler.ru,SOURCE_CATEGORY_SEARCH +mail.yandex.ru,SOURCE_CATEGORY_SEARCH +malaysia.search.yahoo.com,SOURCE_CATEGORY_SEARCH +mbga.jp,SOURCE_CATEGORY_SOCIAL +medium.com,SOURCE_CATEGORY_SOCIAL +meetin.org,SOURCE_CATEGORY_SOCIAL +meetup,SOURCE_CATEGORY_SOCIAL +meetup.com,SOURCE_CATEGORY_SOCIAL +meinvz.net,SOURCE_CATEGORY_SOCIAL +meneame.net,SOURCE_CATEGORY_SOCIAL +menuism.com,SOURCE_CATEGORY_SOCIAL +mercadolibre,SOURCE_CATEGORY_SHOPPING +mercadolibre.com,SOURCE_CATEGORY_SHOPPING +mercadolibre.com.ar,SOURCE_CATEGORY_SHOPPING +mercadolibre.com.mx,SOURCE_CATEGORY_SHOPPING +message.alibaba.com,SOURCE_CATEGORY_SHOPPING +messages.google.com,SOURCE_CATEGORY_SOCIAL +messages.yahoo.co.jp,SOURCE_CATEGORY_SOCIAL +messenger,SOURCE_CATEGORY_SOCIAL +messenger.com,SOURCE_CATEGORY_SOCIAL +mix.com,SOURCE_CATEGORY_SOCIAL +mixi.jp,SOURCE_CATEGORY_SOCIAL +mobile.facebook.com,SOURCE_CATEGORY_SOCIAL +mocospace,SOURCE_CATEGORY_SOCIAL +mocospace.com,SOURCE_CATEGORY_SOCIAL +mouthshut,SOURCE_CATEGORY_SOCIAL +mouthshut.com,SOURCE_CATEGORY_SOCIAL +movabletype,SOURCE_CATEGORY_SOCIAL +movabletype.com,SOURCE_CATEGORY_SOCIAL +msearch.shopping.naver.com,SOURCE_CATEGORY_SHOPPING +msn,SOURCE_CATEGORY_SEARCH +msn.com,SOURCE_CATEGORY_SEARCH +mubi,SOURCE_CATEGORY_SOCIAL +mubi.com,SOURCE_CATEGORY_SOCIAL +music.youtube.com,SOURCE_CATEGORY_VIDEO +mx.search.yahoo.com,SOURCE_CATEGORY_SEARCH +my.opera.com,SOURCE_CATEGORY_SOCIAL +myanimelist.net,SOURCE_CATEGORY_SOCIAL +myheritage,SOURCE_CATEGORY_SOCIAL +myheritage.com,SOURCE_CATEGORY_SOCIAL +mylife,SOURCE_CATEGORY_SOCIAL +mylife.com,SOURCE_CATEGORY_SOCIAL +mymodernmet,SOURCE_CATEGORY_SOCIAL +mymodernmet.com,SOURCE_CATEGORY_SOCIAL +myspace,SOURCE_CATEGORY_SOCIAL +myspace.com,SOURCE_CATEGORY_SOCIAL +najdi,SOURCE_CATEGORY_SEARCH +naver,SOURCE_CATEGORY_SEARCH +naver.com,SOURCE_CATEGORY_SEARCH +netflix,SOURCE_CATEGORY_VIDEO +netflix.com,SOURCE_CATEGORY_VIDEO +netvibes,SOURCE_CATEGORY_SOCIAL +netvibes.com,SOURCE_CATEGORY_SOCIAL +news.google.com,SOURCE_CATEGORY_SEARCH +news.ycombinator.com,SOURCE_CATEGORY_SOCIAL +newsshowcase,SOURCE_CATEGORY_SOCIAL +nexopia,SOURCE_CATEGORY_SOCIAL +ngopost.org,SOURCE_CATEGORY_SOCIAL +niconico,SOURCE_CATEGORY_SOCIAL +nicovideo.jp,SOURCE_CATEGORY_SOCIAL +nightlifelink,SOURCE_CATEGORY_SOCIAL +nightlifelink.com,SOURCE_CATEGORY_SOCIAL +ning,SOURCE_CATEGORY_SOCIAL +ning.com,SOURCE_CATEGORY_SOCIAL +nl.pinterest.com,SOURCE_CATEGORY_SOCIAL +nl.search.yahoo.com,SOURCE_CATEGORY_SEARCH +nl.shopping.net,SOURCE_CATEGORY_SHOPPING +no.search.yahoo.com,SOURCE_CATEGORY_SEARCH +no.shopping.net,SOURCE_CATEGORY_SHOPPING +ntp.msn.com,SOURCE_CATEGORY_SEARCH +nz.search.yahoo.com,SOURCE_CATEGORY_SEARCH +odnoklassniki.ru,SOURCE_CATEGORY_SOCIAL +odnoklassniki.ua,SOURCE_CATEGORY_SOCIAL +offer.alibaba.com,SOURCE_CATEGORY_SHOPPING +okwave.jp,SOURCE_CATEGORY_SOCIAL +old.reddit.com,SOURCE_CATEGORY_SOCIAL +one.walmart.com,SOURCE_CATEGORY_SHOPPING +onet,SOURCE_CATEGORY_SEARCH +onet.pl,SOURCE_CATEGORY_SEARCH +oneworldgroup.org,SOURCE_CATEGORY_SOCIAL +onstartups,SOURCE_CATEGORY_SOCIAL +onstartups.com,SOURCE_CATEGORY_SOCIAL +opendiary,SOURCE_CATEGORY_SOCIAL +opendiary.com,SOURCE_CATEGORY_SOCIAL +order.shopping.yahoo.co.jp,SOURCE_CATEGORY_SHOPPING +oshiete.goo.ne.jp,SOURCE_CATEGORY_SOCIAL +out.reddit.com,SOURCE_CATEGORY_SOCIAL +over-blog.com,SOURCE_CATEGORY_SOCIAL +overblog.com,SOURCE_CATEGORY_SOCIAL +paper.li,SOURCE_CATEGORY_SOCIAL +partners.shopify.com,SOURCE_CATEGORY_SHOPPING +partyflock.nl,SOURCE_CATEGORY_SOCIAL +pe.search.yahoo.com,SOURCE_CATEGORY_SEARCH +ph.search.yahoo.com,SOURCE_CATEGORY_SEARCH +photobucket,SOURCE_CATEGORY_SOCIAL +photobucket.com,SOURCE_CATEGORY_SOCIAL +pinboard,SOURCE_CATEGORY_SOCIAL +pinboard.in,SOURCE_CATEGORY_SOCIAL +pingsta,SOURCE_CATEGORY_SOCIAL +pingsta.com,SOURCE_CATEGORY_SOCIAL +pinterest,SOURCE_CATEGORY_SOCIAL +pinterest.at,SOURCE_CATEGORY_SOCIAL +pinterest.ca,SOURCE_CATEGORY_SOCIAL +pinterest.ch,SOURCE_CATEGORY_SOCIAL +pinterest.cl,SOURCE_CATEGORY_SOCIAL +pinterest.co.kr,SOURCE_CATEGORY_SOCIAL +pinterest.co.uk,SOURCE_CATEGORY_SOCIAL +pinterest.com,SOURCE_CATEGORY_SOCIAL +pinterest.com.au,SOURCE_CATEGORY_SOCIAL +pinterest.com.mx,SOURCE_CATEGORY_SOCIAL +pinterest.de,SOURCE_CATEGORY_SOCIAL +pinterest.es,SOURCE_CATEGORY_SOCIAL +pinterest.fr,SOURCE_CATEGORY_SOCIAL +pinterest.it,SOURCE_CATEGORY_SOCIAL +pinterest.jp,SOURCE_CATEGORY_SOCIAL +pinterest.nz,SOURCE_CATEGORY_SOCIAL +pinterest.ph,SOURCE_CATEGORY_SOCIAL +pinterest.pt,SOURCE_CATEGORY_SOCIAL +pinterest.ru,SOURCE_CATEGORY_SOCIAL +pinterest.se,SOURCE_CATEGORY_SOCIAL +pixiv.net,SOURCE_CATEGORY_SOCIAL +pl.pinterest.com,SOURCE_CATEGORY_SOCIAL +pl.search.yahoo.com,SOURCE_CATEGORY_SEARCH +play.google.com,SOURCE_CATEGORY_SEARCH +playahead.se,SOURCE_CATEGORY_SOCIAL +player.twitch.tv,SOURCE_CATEGORY_VIDEO +player.vimeo.com,SOURCE_CATEGORY_VIDEO +plurk,SOURCE_CATEGORY_SOCIAL +plurk.com,SOURCE_CATEGORY_SOCIAL +plus.google.com,SOURCE_CATEGORY_SOCIAL +plus.url.google.com,SOURCE_CATEGORY_SOCIAL +pocket.co,SOURCE_CATEGORY_SOCIAL +posterous,SOURCE_CATEGORY_SOCIAL +posterous.com,SOURCE_CATEGORY_SOCIAL +pro.homeadvisor.com,SOURCE_CATEGORY_SOCIAL +pulse.yahoo.com,SOURCE_CATEGORY_SOCIAL +qapacity,SOURCE_CATEGORY_SOCIAL +qapacity.com,SOURCE_CATEGORY_SOCIAL +quechup,SOURCE_CATEGORY_SOCIAL +quechup.com,SOURCE_CATEGORY_SOCIAL +quora,SOURCE_CATEGORY_SOCIAL +quora.com,SOURCE_CATEGORY_SOCIAL +qwant,SOURCE_CATEGORY_SEARCH +qwant.com,SOURCE_CATEGORY_SEARCH +qzone.qq.com,SOURCE_CATEGORY_SOCIAL +rakuten,SOURCE_CATEGORY_SEARCH +rakuten.co.jp,SOURCE_CATEGORY_SEARCH +rambler,SOURCE_CATEGORY_SEARCH +rambler.ru,SOURCE_CATEGORY_SEARCH +ravelry,SOURCE_CATEGORY_SOCIAL +ravelry.com,SOURCE_CATEGORY_SOCIAL +reddit,SOURCE_CATEGORY_SOCIAL +reddit.com,SOURCE_CATEGORY_SOCIAL +redux,SOURCE_CATEGORY_SOCIAL +redux.com,SOURCE_CATEGORY_SOCIAL +renren,SOURCE_CATEGORY_SOCIAL +renren.com,SOURCE_CATEGORY_SOCIAL +researchgate.net,SOURCE_CATEGORY_SOCIAL +reunion,SOURCE_CATEGORY_SOCIAL +reunion.com,SOURCE_CATEGORY_SOCIAL +reverbnation,SOURCE_CATEGORY_SOCIAL +reverbnation.com,SOURCE_CATEGORY_SOCIAL +rtl.de,SOURCE_CATEGORY_SOCIAL +ryze,SOURCE_CATEGORY_SOCIAL +ryze.com,SOURCE_CATEGORY_SOCIAL +s3.amazonaws.com,SOURCE_CATEGORY_SHOPPING +salespider,SOURCE_CATEGORY_SOCIAL +salespider.com,SOURCE_CATEGORY_SOCIAL +scoop.it,SOURCE_CATEGORY_SOCIAL +screenrant,SOURCE_CATEGORY_SOCIAL +screenrant.com,SOURCE_CATEGORY_SOCIAL +scribd,SOURCE_CATEGORY_SOCIAL +scribd.com,SOURCE_CATEGORY_SOCIAL +scvngr,SOURCE_CATEGORY_SOCIAL +scvngr.com,SOURCE_CATEGORY_SOCIAL +se.search.yahoo.com,SOURCE_CATEGORY_SEARCH +se.shopping.net,SOURCE_CATEGORY_SHOPPING +search-results,SOURCE_CATEGORY_SEARCH +search.aol.co.uk,SOURCE_CATEGORY_SEARCH +search.aol.com,SOURCE_CATEGORY_SEARCH +search.google.com,SOURCE_CATEGORY_SEARCH +search.smt.docomo.ne.jp,SOURCE_CATEGORY_SEARCH +search.ukr.net,SOURCE_CATEGORY_SEARCH +secondlife,SOURCE_CATEGORY_SOCIAL +secondlife.com,SOURCE_CATEGORY_SOCIAL +secureurl.ukr.net,SOURCE_CATEGORY_SEARCH +serverfault,SOURCE_CATEGORY_SOCIAL +serverfault.com,SOURCE_CATEGORY_SOCIAL +seznam,SOURCE_CATEGORY_SEARCH +seznam.cz,SOURCE_CATEGORY_SEARCH +sg.search.yahoo.com,SOURCE_CATEGORY_SEARCH +shareit,SOURCE_CATEGORY_SOCIAL +sharethis,SOURCE_CATEGORY_SOCIAL +sharethis.com,SOURCE_CATEGORY_SOCIAL +shop.app,SOURCE_CATEGORY_SHOPPING +shopify,SOURCE_CATEGORY_SHOPPING +shopify.com,SOURCE_CATEGORY_SHOPPING +shopping.naver.com,SOURCE_CATEGORY_SHOPPING +shopping.yahoo.co.jp,SOURCE_CATEGORY_SHOPPING +shopping.yahoo.com,SOURCE_CATEGORY_SHOPPING +shopzilla,SOURCE_CATEGORY_SHOPPING +shopzilla.com,SOURCE_CATEGORY_SHOPPING +shvoong.com,SOURCE_CATEGORY_SOCIAL +simplycodes.com,SOURCE_CATEGORY_SHOPPING +sites.google.com,SOURCE_CATEGORY_SOCIAL +skype,SOURCE_CATEGORY_SOCIAL +skyrock,SOURCE_CATEGORY_SOCIAL +skyrock.com,SOURCE_CATEGORY_SOCIAL +slashdot.org,SOURCE_CATEGORY_SOCIAL +slideshare.net,SOURCE_CATEGORY_SOCIAL +smartnews.com,SOURCE_CATEGORY_SOCIAL +snapchat,SOURCE_CATEGORY_SOCIAL +snapchat.com,SOURCE_CATEGORY_SOCIAL +so.com,SOURCE_CATEGORY_SEARCH +social,SOURCE_CATEGORY_SOCIAL +sociallife.com.br,SOURCE_CATEGORY_SOCIAL +socialvibe,SOURCE_CATEGORY_SOCIAL +socialvibe.com,SOURCE_CATEGORY_SOCIAL +sogou,SOURCE_CATEGORY_SEARCH +sogou.com,SOURCE_CATEGORY_SEARCH +sp-web.search.auone.jp,SOURCE_CATEGORY_SEARCH +spaces.live.com,SOURCE_CATEGORY_SOCIAL +spoke,SOURCE_CATEGORY_SOCIAL +spoke.com,SOURCE_CATEGORY_SOCIAL +spruz,SOURCE_CATEGORY_SOCIAL +spruz.com,SOURCE_CATEGORY_SOCIAL +ssense.com,SOURCE_CATEGORY_SOCIAL +stackapps,SOURCE_CATEGORY_SOCIAL +stackapps.com,SOURCE_CATEGORY_SOCIAL +stackexchange,SOURCE_CATEGORY_SOCIAL +stackexchange.com,SOURCE_CATEGORY_SOCIAL +stackoverflow,SOURCE_CATEGORY_SOCIAL +stackoverflow.com,SOURCE_CATEGORY_SOCIAL +stardoll.com,SOURCE_CATEGORY_SOCIAL +startsiden,SOURCE_CATEGORY_SEARCH +startsiden.no,SOURCE_CATEGORY_SEARCH +stickam,SOURCE_CATEGORY_SOCIAL +stickam.com,SOURCE_CATEGORY_SOCIAL +store.shopping.yahoo.co.jp,SOURCE_CATEGORY_SHOPPING +stripe,SOURCE_CATEGORY_SHOPPING +stripe.com,SOURCE_CATEGORY_SHOPPING +studivz.net,SOURCE_CATEGORY_SOCIAL +suche.aol.de,SOURCE_CATEGORY_SEARCH +suomi24.fi,SOURCE_CATEGORY_SOCIAL +superuser,SOURCE_CATEGORY_SOCIAL +superuser.com,SOURCE_CATEGORY_SOCIAL +sweeva,SOURCE_CATEGORY_SOCIAL +sweeva.com,SOURCE_CATEGORY_SOCIAL +t.co,SOURCE_CATEGORY_SOCIAL +t.me,SOURCE_CATEGORY_SOCIAL +tagged,SOURCE_CATEGORY_SOCIAL +tagged.com,SOURCE_CATEGORY_SOCIAL +taggedmail,SOURCE_CATEGORY_SOCIAL +taggedmail.com,SOURCE_CATEGORY_SOCIAL +talkbiznow,SOURCE_CATEGORY_SOCIAL +talkbiznow.com,SOURCE_CATEGORY_SOCIAL +taringa.net,SOURCE_CATEGORY_SOCIAL +techmeme,SOURCE_CATEGORY_SOCIAL +techmeme.com,SOURCE_CATEGORY_SOCIAL +ted,SOURCE_CATEGORY_VIDEO +ted.com,SOURCE_CATEGORY_VIDEO +tencent,SOURCE_CATEGORY_SOCIAL +tencent.com,SOURCE_CATEGORY_SOCIAL +terra,SOURCE_CATEGORY_SEARCH +th.search.yahoo.com,SOURCE_CATEGORY_SEARCH +tiktok,SOURCE_CATEGORY_SOCIAL +tiktok.com,SOURCE_CATEGORY_SOCIAL +tinyurl,SOURCE_CATEGORY_SOCIAL +tinyurl.com,SOURCE_CATEGORY_SOCIAL +toolbox,SOURCE_CATEGORY_SOCIAL +toolbox.com,SOURCE_CATEGORY_SOCIAL +touch.facebook.com,SOURCE_CATEGORY_SOCIAL +tr.pinterest.com,SOURCE_CATEGORY_SOCIAL +tr.search.yahoo.com,SOURCE_CATEGORY_SEARCH +travellerspoint,SOURCE_CATEGORY_SOCIAL +travellerspoint.com,SOURCE_CATEGORY_SOCIAL +tripadvisor,SOURCE_CATEGORY_SOCIAL +tripadvisor.com,SOURCE_CATEGORY_SOCIAL +trombi,SOURCE_CATEGORY_SOCIAL +trombi.com,SOURCE_CATEGORY_SOCIAL +trustpilot,SOURCE_CATEGORY_SOCIAL +tudou,SOURCE_CATEGORY_SOCIAL +tudou.com,SOURCE_CATEGORY_SOCIAL +tuenti,SOURCE_CATEGORY_SOCIAL +tuenti.com,SOURCE_CATEGORY_SOCIAL +tumblr,SOURCE_CATEGORY_SOCIAL +tumblr.com,SOURCE_CATEGORY_SOCIAL +tut.by,SOURCE_CATEGORY_SEARCH +tw.search.yahoo.com,SOURCE_CATEGORY_SEARCH +tweetdeck,SOURCE_CATEGORY_SOCIAL +tweetdeck.com,SOURCE_CATEGORY_SOCIAL +twitch,SOURCE_CATEGORY_VIDEO +twitch.tv,SOURCE_CATEGORY_VIDEO +twitter,SOURCE_CATEGORY_SOCIAL +twitter.com,SOURCE_CATEGORY_SOCIAL +twoo.com,SOURCE_CATEGORY_SOCIAL +typepad,SOURCE_CATEGORY_SOCIAL +typepad.com,SOURCE_CATEGORY_SOCIAL +uk.search.yahoo.com,SOURCE_CATEGORY_SEARCH +uk.shopping.net,SOURCE_CATEGORY_SHOPPING +ukr,SOURCE_CATEGORY_SEARCH +unblog.fr,SOURCE_CATEGORY_SOCIAL +urbanspoon.com,SOURCE_CATEGORY_SOCIAL +us.search.yahoo.com,SOURCE_CATEGORY_SEARCH +ushareit.com,SOURCE_CATEGORY_SOCIAL +ushi.cn,SOURCE_CATEGORY_SOCIAL +utreon,SOURCE_CATEGORY_VIDEO +utreon.com,SOURCE_CATEGORY_VIDEO +vampirefreaks,SOURCE_CATEGORY_SOCIAL +vampirefreaks.com,SOURCE_CATEGORY_SOCIAL +vampirerave,SOURCE_CATEGORY_SOCIAL +vampirerave.com,SOURCE_CATEGORY_SOCIAL +veoh,SOURCE_CATEGORY_VIDEO +veoh.com,SOURCE_CATEGORY_VIDEO +vg.no,SOURCE_CATEGORY_SOCIAL +viadeo.journaldunet.com,SOURCE_CATEGORY_VIDEO +video.ibm.com,SOURCE_CATEGORY_SOCIAL +vimeo,SOURCE_CATEGORY_VIDEO +vimeo.com,SOURCE_CATEGORY_VIDEO +virgilio,SOURCE_CATEGORY_SEARCH +vk.com,SOURCE_CATEGORY_SOCIAL +vkontakte.ru,SOURCE_CATEGORY_SOCIAL +vn.search.yahoo.com,SOURCE_CATEGORY_SEARCH +wakoopa,SOURCE_CATEGORY_SOCIAL +wakoopa.com,SOURCE_CATEGORY_SOCIAL +walmart,SOURCE_CATEGORY_SHOPPING +walmart.com,SOURCE_CATEGORY_SHOPPING +wap.sogou.com,SOURCE_CATEGORY_SEARCH +wattpad,SOURCE_CATEGORY_SOCIAL +wattpad.com,SOURCE_CATEGORY_SOCIAL +web.facebook.com,SOURCE_CATEGORY_SOCIAL +web.skype.com,SOURCE_CATEGORY_SOCIAL +webmaster.yandex.ru,SOURCE_CATEGORY_SEARCH +websearch.rakuten.co.jp,SOURCE_CATEGORY_SEARCH +webshots,SOURCE_CATEGORY_SOCIAL +webshots.com,SOURCE_CATEGORY_SOCIAL +wechat,SOURCE_CATEGORY_SOCIAL +wechat.com,SOURCE_CATEGORY_SOCIAL +weebly,SOURCE_CATEGORY_SOCIAL +weebly.com,SOURCE_CATEGORY_SOCIAL +weibo,SOURCE_CATEGORY_SOCIAL +weibo.com,SOURCE_CATEGORY_SOCIAL +wer-weiss-was.de,SOURCE_CATEGORY_SOCIAL +weread,SOURCE_CATEGORY_SOCIAL +weread.com,SOURCE_CATEGORY_SOCIAL +whatsapp,SOURCE_CATEGORY_SOCIAL +whatsapp.com,SOURCE_CATEGORY_SOCIAL +wiki.answers.com,SOURCE_CATEGORY_SOCIAL +wikihow.com,SOURCE_CATEGORY_SOCIAL +wikitravel.org,SOURCE_CATEGORY_SOCIAL +wistia,SOURCE_CATEGORY_VIDEO +wistia.com,SOURCE_CATEGORY_VIDEO +woot.com,SOURCE_CATEGORY_SOCIAL +wordpress,SOURCE_CATEGORY_SOCIAL +wordpress.com,SOURCE_CATEGORY_SOCIAL +wordpress.org,SOURCE_CATEGORY_SOCIAL +xanga,SOURCE_CATEGORY_SOCIAL +xanga.com,SOURCE_CATEGORY_SOCIAL +xing,SOURCE_CATEGORY_SOCIAL +xing.com,SOURCE_CATEGORY_SOCIAL +yahoo,SOURCE_CATEGORY_SEARCH +yahoo-mbga.jp,SOURCE_CATEGORY_SOCIAL +yahoo.co.jp,SOURCE_CATEGORY_SEARCH +yahoo.com,SOURCE_CATEGORY_SEARCH +yammer,SOURCE_CATEGORY_SOCIAL +yammer.com,SOURCE_CATEGORY_SOCIAL +yandex,SOURCE_CATEGORY_SEARCH +yandex.by,SOURCE_CATEGORY_SEARCH +yandex.com,SOURCE_CATEGORY_SEARCH +yandex.com.tr,SOURCE_CATEGORY_SEARCH +yandex.fr,SOURCE_CATEGORY_SEARCH +yandex.kz,SOURCE_CATEGORY_SEARCH +yandex.ru,SOURCE_CATEGORY_SEARCH +yandex.ua,SOURCE_CATEGORY_SEARCH +yandex.uz,SOURCE_CATEGORY_SEARCH +yelp,SOURCE_CATEGORY_SOCIAL +yelp.co.uk,SOURCE_CATEGORY_SOCIAL +yelp.com,SOURCE_CATEGORY_SOCIAL +youku,SOURCE_CATEGORY_VIDEO +youku.com,SOURCE_CATEGORY_VIDEO +youroom.in,SOURCE_CATEGORY_SOCIAL +youtube,SOURCE_CATEGORY_VIDEO +youtube.com,SOURCE_CATEGORY_VIDEO +za.pinterest.com,SOURCE_CATEGORY_SOCIAL +zalo,SOURCE_CATEGORY_SOCIAL +zen.yandex.ru,SOURCE_CATEGORY_SEARCH +zoo.gr,SOURCE_CATEGORY_SOCIAL +zooppa,SOURCE_CATEGORY_SOCIAL +zooppa.com,SOURCE_CATEGORY_SOCIAL diff --git a/test/plausible_web/controllers/api/external_controller_test.exs b/test/plausible_web/controllers/api/external_controller_test.exs index 80c5a4296..0e33cbc4e 100644 --- a/test/plausible_web/controllers/api/external_controller_test.exs +++ b/test/plausible_web/controllers/api/external_controller_test.exs @@ -1219,6 +1219,731 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do end end + describe "acquisition channel tests" do + setup do + site = insert(:site) + {:ok, site: site} + end + + test "parses cross network channel", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com/?utm_campaign=cross-network", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Cross-network" + end + + test "parses paid shopping channel based on campaign/medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com/?utm_campaign=shopping&utm_medium=paid", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Shopping" + end + + test "parses paid shopping channel based on referrer source and medium", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=paid", + referrer: "https://shopify.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Shopping" + end + + test "parses paid shopping channel based on referrer utm_source and medium", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=shopify&utm_medium=paid", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Shopping" + end + + test "parses paid search channel based on referrer and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=paid", + referrer: "https://duckduckgo.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Search" + end + + test "parses paid search channel based on gclid", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?gclid=123identifier", + referrer: "https://google.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Search" + end + + test "is not paid search when gclid is present on non-google referrer", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com?gclid=123identifier", + referrer: "https://duckduckgo.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Search" + end + + test "parses paid search channel based on msclkid", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?msclkid=123identifier", + referrer: "https://bing.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Search" + end + + test "is not paid search when msclkid is present on non-bing referrer", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com?msclkid=123identifier", + referrer: "https://duckduckgo.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Search" + end + + test "parses paid search channel based on utm_source and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=google&utm_medium=paid", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Search" + end + + test "parses paid social channel based on referrer and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=paid", + referrer: "https://tiktok.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Social" + end + + test "parses paid social channel based on utm_source and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=tiktok&utm_medium=paid", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Social" + end + + test "parses paid video channel based on referrer and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=paid", + referrer: "https://youtube.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Video" + end + + test "parses paid video channel based on utm_source and medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=youtube&utm_medium=paid", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Video" + end + + test "parses display channel", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=banner", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Display" + end + + test "parses paid other channel", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=cpc", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Paid Other" + end + + test "parses organic shopping channel from referrer", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com", + referrer: "https://walmart.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Shopping" + end + + test "parses organic shopping channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=walmart", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Shopping" + end + + test "parses organic shopping channel from utm_campaign", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_campaign=shop", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Shopping" + end + + test "parses organic social channel from referrer", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com", + referrer: "http://facebook.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Social" + end + + test "parses organic social channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=twitter", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Social" + end + + test "parses organic social channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=social", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Social" + end + + test "parses organic video channel from referrer", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com", + referrer: "https://vimeo.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Video" + end + + test "parses organic video channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=vimeo", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Video" + end + + test "parses organic video channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=video", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Video" + end + + test "parses organic search channel from referrer", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com", + referrer: "http://duckduckgo.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Search" + end + + test "parses organic search channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=duckduckgo", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Organic Search" + end + + test "parses referral channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=referral", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Referral" + end + + test "parses email channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=email", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Email" + end + + test "parses email channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=email", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Email" + end + + test "parses affiliates channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=affiliate", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Affiliates" + end + + test "parses audio channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=audio", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Audio" + end + + test "parses sms channel from utm_source", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_source=sms", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "SMS" + end + + test "parses sms channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=sms", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "SMS" + end + + test "parses mobile push notifications channel from utm_medium with push", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=app-push", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Mobile Push Notifications" + end + + test "parses mobile push notifications channel from utm_medium", %{conn: conn, site: site} do + params = %{ + name: "pageview", + url: "http://example.com?utm_medium=example-mobile", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Mobile Push Notifications" + end + + test "parses referral channel if session starts with a simple referral", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com", + referrer: "https://othersite.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Referral" + end + + test "parses direct channel if session starts without referrer or utm tags", %{ + conn: conn, + site: site + } do + params = %{ + name: "pageview", + url: "http://example.com", + domain: site.domain + } + + conn = + conn + |> put_req_header("user-agent", @user_agent) + |> post("/api/event", params) + + session = get_created_session(site) + + assert response(conn, 202) == "ok" + assert session.channel == "Direct" + end + end + describe "user_id generation" do setup do site = insert(:site)