From 2f6c18a6cac07034ad6797da0af0d4965d764add Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Thu, 4 Jan 2018 15:51:36 +0100 Subject: [PATCH 1/8] Add function to extract project id from resources --- .../analytics/segment_data_extractor.ex | 8 +++++++ .../analytics/segment_data_extractor_test.exs | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/lib/code_corps/analytics/segment_data_extractor_test.exs diff --git a/lib/code_corps/analytics/segment_data_extractor.ex b/lib/code_corps/analytics/segment_data_extractor.ex index d5c0f724d..6aaa0e47f 100644 --- a/lib/code_corps/analytics/segment_data_extractor.ex +++ b/lib/code_corps/analytics/segment_data_extractor.ex @@ -23,4 +23,12 @@ defmodule CodeCorps.Analytics.SegmentDataExtractor do def get_user_id(%Plug.Conn{assigns: %{current_user: %CodeCorps.User{id: id}}}, _), do: id def get_user_id(_, %CodeCorps.User{id: id}), do: id def get_user_id(_, %{user_id: user_id}), do: user_id + + @doc """ + Tries to extract project id from given resource. + Returns `nil` if project id can't be extracted. + """ + @spec get_project_id(CodeCorps.ProjectUser.t) :: String.t | nil + def get_project_id(%CodeCorps.ProjectUser{project_id: id}), do: "project_#{id}" + def get_project_id(_), do: nil end diff --git a/test/lib/code_corps/analytics/segment_data_extractor_test.exs b/test/lib/code_corps/analytics/segment_data_extractor_test.exs new file mode 100644 index 000000000..097e65b99 --- /dev/null +++ b/test/lib/code_corps/analytics/segment_data_extractor_test.exs @@ -0,0 +1,23 @@ +defmodule CodeCorps.Analytics.SegmentDataExtractorTest do + @moduledoc false + + use ExUnit.Case, async: true + + import CodeCorps.Factories + + alias CodeCorps.Analytics.SegmentDataExtractor + + describe "get_project_id/1" do + test "should return correct id for project user" do + project_user = build(:project_user) + project_id = "project_#{project_user.project_id}" + + assert SegmentDataExtractor.get_project_id(project_user) == project_id + end + + test "should return nil for unknown resource" do + assert SegmentDataExtractor.get_project_id(%{}) == nil + end + end + +end From 24ffd7c01a97450ba1e4e9fc253c8f4b3c4126c8 Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Mon, 8 Jan 2018 16:52:09 +0100 Subject: [PATCH 2/8] Add event tracking for projects to segment plug --- lib/code_corps/analytics/segment_plug_tracker.ex | 6 ++++++ .../controllers/project_user_controller_test.exs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/lib/code_corps/analytics/segment_plug_tracker.ex b/lib/code_corps/analytics/segment_plug_tracker.ex index d9dbc7545..df4d1a608 100644 --- a/lib/code_corps/analytics/segment_plug_tracker.ex +++ b/lib/code_corps/analytics/segment_plug_tracker.ex @@ -19,6 +19,12 @@ defmodule CodeCorps.Analytics.SegmentPlugTracker do if successful? && SegmentTrackingSupport.includes?(action, resource) do user_id = SegmentDataExtractor.get_user_id(conn, resource) SegmentTracker.track(user_id, action, resource) + + project_id = SegmentDataExtractor.get_project_id(resource) + if project_id do + SegmentTracker.track(project_id, action, resource) + end + mark_tracked(conn) else mark_untracked(conn) diff --git a/test/lib/code_corps_web/controllers/project_user_controller_test.exs b/test/lib/code_corps_web/controllers/project_user_controller_test.exs index b41da48e8..3ca9b9bc3 100644 --- a/test/lib/code_corps_web/controllers/project_user_controller_test.exs +++ b/test/lib/code_corps_web/controllers/project_user_controller_test.exs @@ -49,6 +49,7 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do assert conn |> request_create(attrs) |> json_response(201) user_id = user.id + project_id = "project_#{project.id}" tracking_properties = %{ project: project.title, @@ -58,6 +59,7 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do } assert_received {:track, ^user_id, "Requested Project Membership", ^tracking_properties} + assert_received {:track, ^project_id, "Requested Project Membership", ^tracking_properties} email = CodeCorps.ProjectUser @@ -106,6 +108,7 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do assert json["data"]["attributes"]["role"] == "contributor" user_id = current_user.id + project_id = "project_#{project.id}" tracking_properties = %{ project: project.title, @@ -115,6 +118,7 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do } assert_received {:track, ^user_id, "Approved Project Membership", ^tracking_properties} + assert_received {:track, ^project_id, "Approved Project Membership", ^tracking_properties} email = CodeCorps.ProjectUser From d37bbe9831dd8f96314c57fe4c3653a1b5eb29a2 Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Thu, 11 Jan 2018 12:23:39 +0100 Subject: [PATCH 3/8] Add event direction to tracking event names --- .../analytics/segment_event_name_builder.ex | 42 ++++++++++++------- lib/code_corps/analytics/segment_tracker.ex | 6 +-- .../analytics/segment_tracking_support.ex | 8 ++++ .../segment_event_name_builder_test.exs | 28 +++++++------ .../project_user_controller_test.exs | 8 ++-- 5 files changed, 56 insertions(+), 36 deletions(-) diff --git a/lib/code_corps/analytics/segment_event_name_builder.ex b/lib/code_corps/analytics/segment_event_name_builder.ex index 00a89e161..f91c19f95 100644 --- a/lib/code_corps/analytics/segment_event_name_builder.ex +++ b/lib/code_corps/analytics/segment_event_name_builder.ex @@ -3,33 +3,43 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilder do Used for building friendly event names for use in Segment tracking """ - @spec build(atom, struct) :: String.t - def build(action, record), do: get_event_name(action, record) + alias CodeCorps.Analytics.SegmentTrackingSupport + + @spec build(String.t, atom, struct) :: String.t + def build(id, action, record), do: get_event_name(id, action, record) @actions_without_properties [:updated_profile, :signed_in, :signed_out, :signed_up] - defp get_event_name(action, _) when action in @actions_without_properties do + defp get_event_name(_, action, _) when action in @actions_without_properties do friendly_action_name(action) end - defp get_event_name(:update, %CodeCorps.DonationGoal{}) do + defp get_event_name(_, :update, %CodeCorps.DonationGoal{}) do "Updated Donation Goal" end - defp get_event_name(:create, %CodeCorps.ProjectUser{}) do - "Requested Project Membership" + defp get_event_name(id, :create, %CodeCorps.ProjectUser{}) do + if SegmentTrackingSupport.project_id?(id) do + "Membership Requested (Project)" + else + "Requested Membership (User)" + end end - defp get_event_name(:update, %CodeCorps.ProjectUser{}) do - "Approved Project Membership" + defp get_event_name(id, :update, %CodeCorps.ProjectUser{}) do + if SegmentTrackingSupport.project_id?(id) do + "Approved Membership (Project)" + else + "Membership Approved (User)" + end end - defp get_event_name(:payment_succeeded, %CodeCorps.StripeInvoice{}) do + defp get_event_name(_, :payment_succeeded, %CodeCorps.StripeInvoice{}) do "Processed Subscription Payment" end - defp get_event_name(:create, %CodeCorps.User{}), do: "Signed Up" - defp get_event_name(:update, %CodeCorps.User{}), do: "Updated Profile" - defp get_event_name(:create, %CodeCorps.UserCategory{}), do: "Added User Category" - defp get_event_name(:create, %CodeCorps.UserSkill{}), do: "Added User Skill" - defp get_event_name(:create, %CodeCorps.UserRole{}), do: "Added User Role" - defp get_event_name(:create, %{token: _, user_id: _}), do: "Signed In" - defp get_event_name(action, model) do + defp get_event_name(_, :create, %CodeCorps.User{}), do: "Signed Up" + defp get_event_name(_, :update, %CodeCorps.User{}), do: "Updated Profile" + defp get_event_name(_, :create, %CodeCorps.UserCategory{}), do: "Added User Category" + defp get_event_name(_, :create, %CodeCorps.UserSkill{}), do: "Added User Skill" + defp get_event_name(_, :create, %CodeCorps.UserRole{}), do: "Added User Role" + defp get_event_name(_, :create, %{token: _, user_id: _}), do: "Signed In" + defp get_event_name(_, action, model) do [friendly_action_name(action), friendly_model_name(model)] |> Enum.join(" ") end diff --git a/lib/code_corps/analytics/segment_tracker.ex b/lib/code_corps/analytics/segment_tracker.ex index 241592adb..1240e42a6 100644 --- a/lib/code_corps/analytics/segment_tracker.ex +++ b/lib/code_corps/analytics/segment_tracker.ex @@ -22,10 +22,10 @@ defmodule CodeCorps.Analytics.SegmentTracker do Calls `track` in the configured API module. """ @spec track(String.t, atom | String.t, struct) :: any - def track(user_id, action, data) when is_atom(action) do - event = SegmentEventNameBuilder.build(action, data) + def track(id, action, data) when is_atom(action) do + event = SegmentEventNameBuilder.build(id, action, data) traits = SegmentTraitsBuilder.build(data) - @api.track(user_id, event, traits) + @api.track(id, event, traits) end def track(user_id, event, data) when is_binary(event) do traits = SegmentTraitsBuilder.build(data) diff --git a/lib/code_corps/analytics/segment_tracking_support.ex b/lib/code_corps/analytics/segment_tracking_support.ex index 301bfb01f..643d4b0b5 100644 --- a/lib/code_corps/analytics/segment_tracking_support.ex +++ b/lib/code_corps/analytics/segment_tracking_support.ex @@ -29,4 +29,12 @@ defmodule CodeCorps.Analytics.SegmentTrackingSupport do def includes?(:delete, %CodeCorps.UserSkill{}), do: true def includes?(:create, %{token: _, user_id: _}), do: true def includes?(_, _), do: false + + + @doc """ + Determines whether event id is tracking project. + """ + @spec project_id?(String.t | integer) :: boolean + def project_id?(event_id) when is_integer(event_id), do: false + def project_id?(event_id), do: String.starts_with?(event_id, "project_") end diff --git a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs index 053a071a3..88392f157 100644 --- a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs @@ -9,37 +9,39 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilderTest do describe "get_action_name/2" do test "with comment" do - assert SegmentEventNameBuilder.build(:create, build(:comment)) == "Created Comment" - assert SegmentEventNameBuilder.build(:update, build(:comment)) == "Edited Comment" + assert SegmentEventNameBuilder.build("1", :create, build(:comment)) == "Created Comment" + assert SegmentEventNameBuilder.build("1", :update, build(:comment)) == "Edited Comment" end test "with project_user" do - assert SegmentEventNameBuilder.build(:create, build(:project_user)) == "Requested Project Membership" - assert SegmentEventNameBuilder.build(:update, build(:project_user)) == "Approved Project Membership" + assert SegmentEventNameBuilder.build("1", :create, build(:project_user)) == "Requested Membership (User)" + assert SegmentEventNameBuilder.build("1", :update, build(:project_user)) == "Membership Approved (User)" + assert SegmentEventNameBuilder.build("project_1", :create, build(:project_user)) == "Membership Requested (Project)" + assert SegmentEventNameBuilder.build("project_2", :update, build(:project_user)) == "Approved Membership (Project)" end test "with task" do - assert SegmentEventNameBuilder.build(:create, build(:task)) == "Created Task" - assert SegmentEventNameBuilder.build(:update, build(:task)) == "Edited Task" + assert SegmentEventNameBuilder.build("1", :create, build(:task)) == "Created Task" + assert SegmentEventNameBuilder.build("1", :update, build(:task)) == "Edited Task" end test "with user" do - assert SegmentEventNameBuilder.build(:create, build(:user)) == "Signed Up" + assert SegmentEventNameBuilder.build("1", :create, build(:user)) == "Signed Up" end test "with user category" do - assert SegmentEventNameBuilder.build(:create, build(:user_category)) == "Added User Category" - assert SegmentEventNameBuilder.build(:delete, build(:user_category)) == "Removed User Category" + assert SegmentEventNameBuilder.build("1", :create, build(:user_category)) == "Added User Category" + assert SegmentEventNameBuilder.build("1", :delete, build(:user_category)) == "Removed User Category" end test "with user role" do - assert SegmentEventNameBuilder.build(:create, build(:user_role)) == "Added User Role" - assert SegmentEventNameBuilder.build(:delete, build(:user_role)) == "Removed User Role" + assert SegmentEventNameBuilder.build("1", :create, build(:user_role)) == "Added User Role" + assert SegmentEventNameBuilder.build("1", :delete, build(:user_role)) == "Removed User Role" end test "with user skill" do - assert SegmentEventNameBuilder.build(:create, build(:user_skill)) == "Added User Skill" - assert SegmentEventNameBuilder.build(:delete, build(:user_skill)) == "Removed User Skill" + assert SegmentEventNameBuilder.build("1", :create, build(:user_skill)) == "Added User Skill" + assert SegmentEventNameBuilder.build("1", :delete, build(:user_skill)) == "Removed User Skill" end end end diff --git a/test/lib/code_corps_web/controllers/project_user_controller_test.exs b/test/lib/code_corps_web/controllers/project_user_controller_test.exs index 3ca9b9bc3..0193ec8e2 100644 --- a/test/lib/code_corps_web/controllers/project_user_controller_test.exs +++ b/test/lib/code_corps_web/controllers/project_user_controller_test.exs @@ -58,8 +58,8 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do member_id: user.id } - assert_received {:track, ^user_id, "Requested Project Membership", ^tracking_properties} - assert_received {:track, ^project_id, "Requested Project Membership", ^tracking_properties} + assert_received {:track, ^user_id, "Requested Membership (User)", ^tracking_properties} + assert_received {:track, ^project_id, "Membership Requested (Project)", ^tracking_properties} email = CodeCorps.ProjectUser @@ -117,8 +117,8 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do member_id: record.user.id } - assert_received {:track, ^user_id, "Approved Project Membership", ^tracking_properties} - assert_received {:track, ^project_id, "Approved Project Membership", ^tracking_properties} + assert_received {:track, ^user_id, "Membership Approved (User)", ^tracking_properties} + assert_received {:track, ^project_id, "Approved Membership (Project)", ^tracking_properties} email = CodeCorps.ProjectUser From aa13ed88aec646064025f506e178ff92db58f8f9 Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Fri, 12 Jan 2018 10:48:41 +0100 Subject: [PATCH 4/8] Move get_project_id to preserve alphabetic ordering. --- .../analytics/segment_data_extractor.ex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/code_corps/analytics/segment_data_extractor.ex b/lib/code_corps/analytics/segment_data_extractor.ex index 6aaa0e47f..7d64678cb 100644 --- a/lib/code_corps/analytics/segment_data_extractor.ex +++ b/lib/code_corps/analytics/segment_data_extractor.ex @@ -7,6 +7,14 @@ defmodule CodeCorps.Analytics.SegmentDataExtractor do def get_action(%Plug.Conn{private: %{phoenix_action: action}}), do: action def get_action(_), do: nil + @doc """ + Tries to extract project id from given resource. + Returns `nil` if project id can't be extracted. + """ + @spec get_project_id(CodeCorps.ProjectUser.t) :: String.t | nil + def get_project_id(%CodeCorps.ProjectUser{project_id: id}), do: "project_#{id}" + def get_project_id(_), do: nil + @spec get_resource(Plug.Conn.t) :: struct def get_resource(%Plug.Conn{assigns: %{data: data}}), do: data # these are used for delete actions on records that support it @@ -23,12 +31,4 @@ defmodule CodeCorps.Analytics.SegmentDataExtractor do def get_user_id(%Plug.Conn{assigns: %{current_user: %CodeCorps.User{id: id}}}, _), do: id def get_user_id(_, %CodeCorps.User{id: id}), do: id def get_user_id(_, %{user_id: user_id}), do: user_id - - @doc """ - Tries to extract project id from given resource. - Returns `nil` if project id can't be extracted. - """ - @spec get_project_id(CodeCorps.ProjectUser.t) :: String.t | nil - def get_project_id(%CodeCorps.ProjectUser{project_id: id}), do: "project_#{id}" - def get_project_id(_), do: nil end From cc2f8c84e7c8b5fcbab7bce7a092f963f4333202 Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Fri, 12 Jan 2018 12:30:32 +0100 Subject: [PATCH 5/8] Add acceptor to project user events Tracking of project user events was moved to project_user controller. This change allows us to use existing tracking api without need of passing additional arguments like current user or action to SegmentTraitsBuilder.build/2 that arent needed in other explicitly tracked events. --- .../analytics/segment_event_name_builder.ex | 16 -------- .../analytics/segment_plug_tracker.ex | 5 --- .../analytics/segment_tracking_support.ex | 10 +---- .../analytics/segment_traits_builder.ex | 5 +++ .../controllers/project_user_controller.ex | 41 ++++++++++++++++++- .../segment_event_name_builder_test.exs | 7 ---- .../analytics/segment_traits_builder_test.exs | 6 +++ .../project_user_controller_test.exs | 4 +- 8 files changed, 55 insertions(+), 39 deletions(-) diff --git a/lib/code_corps/analytics/segment_event_name_builder.ex b/lib/code_corps/analytics/segment_event_name_builder.ex index f91c19f95..b7be17e76 100644 --- a/lib/code_corps/analytics/segment_event_name_builder.ex +++ b/lib/code_corps/analytics/segment_event_name_builder.ex @@ -3,8 +3,6 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilder do Used for building friendly event names for use in Segment tracking """ - alias CodeCorps.Analytics.SegmentTrackingSupport - @spec build(String.t, atom, struct) :: String.t def build(id, action, record), do: get_event_name(id, action, record) @@ -16,20 +14,6 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilder do defp get_event_name(_, :update, %CodeCorps.DonationGoal{}) do "Updated Donation Goal" end - defp get_event_name(id, :create, %CodeCorps.ProjectUser{}) do - if SegmentTrackingSupport.project_id?(id) do - "Membership Requested (Project)" - else - "Requested Membership (User)" - end - end - defp get_event_name(id, :update, %CodeCorps.ProjectUser{}) do - if SegmentTrackingSupport.project_id?(id) do - "Approved Membership (Project)" - else - "Membership Approved (User)" - end - end defp get_event_name(_, :payment_succeeded, %CodeCorps.StripeInvoice{}) do "Processed Subscription Payment" end diff --git a/lib/code_corps/analytics/segment_plug_tracker.ex b/lib/code_corps/analytics/segment_plug_tracker.ex index df4d1a608..4bb88d1a4 100644 --- a/lib/code_corps/analytics/segment_plug_tracker.ex +++ b/lib/code_corps/analytics/segment_plug_tracker.ex @@ -20,11 +20,6 @@ defmodule CodeCorps.Analytics.SegmentPlugTracker do user_id = SegmentDataExtractor.get_user_id(conn, resource) SegmentTracker.track(user_id, action, resource) - project_id = SegmentDataExtractor.get_project_id(resource) - if project_id do - SegmentTracker.track(project_id, action, resource) - end - mark_tracked(conn) else mark_untracked(conn) diff --git a/lib/code_corps/analytics/segment_tracking_support.ex b/lib/code_corps/analytics/segment_tracking_support.ex index 643d4b0b5..6b450256a 100644 --- a/lib/code_corps/analytics/segment_tracking_support.ex +++ b/lib/code_corps/analytics/segment_tracking_support.ex @@ -11,8 +11,6 @@ defmodule CodeCorps.Analytics.SegmentTrackingSupport do def includes?(:update, %CodeCorps.Comment{}), do: true def includes?(:create, %CodeCorps.DonationGoal{}), do: true def includes?(:update, %CodeCorps.DonationGoal{}), do: true - def includes?(:create, %CodeCorps.ProjectUser{}), do: true - def includes?(:update, %CodeCorps.ProjectUser{}), do: true def includes?(:create, %CodeCorps.StripeConnectAccount{}), do: true def includes?(:create, %CodeCorps.StripeConnectCharge{}), do: true def includes?(:create, %CodeCorps.StripeConnectPlan{}), do: true @@ -30,11 +28,5 @@ defmodule CodeCorps.Analytics.SegmentTrackingSupport do def includes?(:create, %{token: _, user_id: _}), do: true def includes?(_, _), do: false - - @doc """ - Determines whether event id is tracking project. - """ - @spec project_id?(String.t | integer) :: boolean - def project_id?(event_id) when is_integer(event_id), do: false - def project_id?(event_id), do: String.starts_with?(event_id, "project_") + def project_id?(id), do: String.starts_with?(id, "project_") end diff --git a/lib/code_corps/analytics/segment_traits_builder.ex b/lib/code_corps/analytics/segment_traits_builder.ex index 3000ba5c0..ae66f51ea 100644 --- a/lib/code_corps/analytics/segment_traits_builder.ex +++ b/lib/code_corps/analytics/segment_traits_builder.ex @@ -225,4 +225,9 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilder do } end defp traits(%{token: _, user_id: _}), do: %{} + defp traits(%{current_user: user, project_user: project_user}) do + project_user + |> traits() + |> Map.merge(%{acceptor_id: user.id, acceptor: user.username}) + end end diff --git a/lib/code_corps_web/controllers/project_user_controller.ex b/lib/code_corps_web/controllers/project_user_controller.ex index 0e41f7861..0a53ed5fb 100644 --- a/lib/code_corps_web/controllers/project_user_controller.ex +++ b/lib/code_corps_web/controllers/project_user_controller.ex @@ -2,7 +2,15 @@ defmodule CodeCorpsWeb.ProjectUserController do @moduledoc false use CodeCorpsWeb, :controller - alias CodeCorps.{Emails, Helpers.Query, Mailer, ProjectUser, User} + alias CodeCorps.{ + Analytics.SegmentTracker, + Analytics.SegmentDataExtractor, + Emails, + Helpers.Query, + Mailer, + ProjectUser, + User + } action_fallback CodeCorpsWeb.FallbackController plug CodeCorpsWeb.Plug.DataToAttributes @@ -31,6 +39,7 @@ defmodule CodeCorpsWeb.ProjectUserController do {:ok, %ProjectUser{} = project_user} <- %ProjectUser{} |> ProjectUser.create_changeset(params) |> Repo.insert, _ <- maybe_send_create_email(project_user) do + track_created(current_user, project_user) conn |> put_status(:created) |> render("show.json-api", data: project_user) end end @@ -43,6 +52,7 @@ defmodule CodeCorpsWeb.ProjectUserController do {:ok, %ProjectUser{} = updated_project_user} <- project_user |> ProjectUser.update_changeset(params) |> Repo.update, _ <- maybe_send_update_email(updated_project_user, project_user) do + track_updated(current_user, project_user) conn |> render("show.json-api", data: updated_project_user) end end @@ -88,4 +98,33 @@ defmodule CodeCorpsWeb.ProjectUserController do |> Emails.ProjectUserAcceptanceEmail.create() |> Mailer.deliver_now() end + + @spec track_created(User.t, ProjectUser.t) :: any + def track_created( + %User{id: user_id}, + %ProjectUser{} = project_user) do + + SegmentTracker.track(user_id, "Requested Membership (User)", project_user) + + project_user + |> SegmentDataExtractor.get_project_id() + |> SegmentTracker.track("Membership Requested (Project)", project_user) + end + + @spec track_updated(User.t, ProjectUser.t) :: any + def track_updated( + %User{id: user_id} = user, + %ProjectUser{} = project_user) do + + data = %{ + current_user: user, + project_user: project_user + } + + SegmentTracker.track(user_id, "Membership Approved (User)", data) + + project_user + |> SegmentDataExtractor.get_project_id() + |> SegmentTracker.track("Approved Membership (Project)", data) + end end diff --git a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs index 88392f157..6f760aa40 100644 --- a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs @@ -13,13 +13,6 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilderTest do assert SegmentEventNameBuilder.build("1", :update, build(:comment)) == "Edited Comment" end - test "with project_user" do - assert SegmentEventNameBuilder.build("1", :create, build(:project_user)) == "Requested Membership (User)" - assert SegmentEventNameBuilder.build("1", :update, build(:project_user)) == "Membership Approved (User)" - assert SegmentEventNameBuilder.build("project_1", :create, build(:project_user)) == "Membership Requested (Project)" - assert SegmentEventNameBuilder.build("project_2", :update, build(:project_user)) == "Approved Membership (Project)" - end - test "with task" do assert SegmentEventNameBuilder.build("1", :create, build(:task)) == "Created Task" assert SegmentEventNameBuilder.build("1", :update, build(:task)) == "Edited Task" diff --git a/test/lib/code_corps/analytics/segment_traits_builder_test.exs b/test/lib/code_corps/analytics/segment_traits_builder_test.exs index 85e387db6..7d1c9f06b 100644 --- a/test/lib/code_corps/analytics/segment_traits_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_traits_builder_test.exs @@ -23,6 +23,12 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilderTest do assert :project_skill |> insert |> SegmentTraitsBuilder.build assert :project_user |> insert |> SegmentTraitsBuilder.build + data = %{ + current_user: insert(:user), + project_user: insert(:project_user) + } + assert SegmentTraitsBuilder.build(data) + assert :stripe_connect_account |> insert |> SegmentTraitsBuilder.build assert :stripe_connect_charge |> insert |> SegmentTraitsBuilder.build assert :stripe_connect_plan |> insert |> SegmentTraitsBuilder.build diff --git a/test/lib/code_corps_web/controllers/project_user_controller_test.exs b/test/lib/code_corps_web/controllers/project_user_controller_test.exs index 0193ec8e2..805d2dc81 100644 --- a/test/lib/code_corps_web/controllers/project_user_controller_test.exs +++ b/test/lib/code_corps_web/controllers/project_user_controller_test.exs @@ -114,7 +114,9 @@ defmodule CodeCorpsWeb.ProjectUserControllerTest do project: project.title, project_id: project.id, member: record.user.username, - member_id: record.user.id + member_id: record.user.id, + acceptor: current_user.username, + acceptor_id: current_user.id } assert_received {:track, ^user_id, "Membership Approved (User)", ^tracking_properties} From 43268dc92bd4f5992b063c13075778e55198c59f Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Fri, 12 Jan 2018 12:36:35 +0100 Subject: [PATCH 6/8] Rename current_user in update event to acceptor --- lib/code_corps/analytics/segment_traits_builder.ex | 2 +- lib/code_corps_web/controllers/project_user_controller.ex | 2 +- test/lib/code_corps/analytics/segment_traits_builder_test.exs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/code_corps/analytics/segment_traits_builder.ex b/lib/code_corps/analytics/segment_traits_builder.ex index ae66f51ea..41608817e 100644 --- a/lib/code_corps/analytics/segment_traits_builder.ex +++ b/lib/code_corps/analytics/segment_traits_builder.ex @@ -225,7 +225,7 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilder do } end defp traits(%{token: _, user_id: _}), do: %{} - defp traits(%{current_user: user, project_user: project_user}) do + defp traits(%{acceptor: user, project_user: project_user}) do project_user |> traits() |> Map.merge(%{acceptor_id: user.id, acceptor: user.username}) diff --git a/lib/code_corps_web/controllers/project_user_controller.ex b/lib/code_corps_web/controllers/project_user_controller.ex index 0a53ed5fb..fe8c05491 100644 --- a/lib/code_corps_web/controllers/project_user_controller.ex +++ b/lib/code_corps_web/controllers/project_user_controller.ex @@ -117,7 +117,7 @@ defmodule CodeCorpsWeb.ProjectUserController do %ProjectUser{} = project_user) do data = %{ - current_user: user, + acceptor: user, project_user: project_user } diff --git a/test/lib/code_corps/analytics/segment_traits_builder_test.exs b/test/lib/code_corps/analytics/segment_traits_builder_test.exs index 7d1c9f06b..7931acc9c 100644 --- a/test/lib/code_corps/analytics/segment_traits_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_traits_builder_test.exs @@ -24,7 +24,7 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilderTest do assert :project_user |> insert |> SegmentTraitsBuilder.build data = %{ - current_user: insert(:user), + acceptor: insert(:user), project_user: insert(:project_user) } assert SegmentTraitsBuilder.build(data) From e42e9aeb302f34dce5a483adec2337ac4dd17951 Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Fri, 12 Jan 2018 12:37:20 +0100 Subject: [PATCH 7/8] Removed unnecessary project_id? function --- lib/code_corps/analytics/segment_tracking_support.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/code_corps/analytics/segment_tracking_support.ex b/lib/code_corps/analytics/segment_tracking_support.ex index 6b450256a..dcdface6a 100644 --- a/lib/code_corps/analytics/segment_tracking_support.ex +++ b/lib/code_corps/analytics/segment_tracking_support.ex @@ -27,6 +27,4 @@ defmodule CodeCorps.Analytics.SegmentTrackingSupport do def includes?(:delete, %CodeCorps.UserSkill{}), do: true def includes?(:create, %{token: _, user_id: _}), do: true def includes?(_, _), do: false - - def project_id?(id), do: String.starts_with?(id, "project_") end From 3257fa7c0086511848a933c2a9053db3827bbb3d Mon Sep 17 00:00:00 2001 From: Jan Ferko Date: Fri, 12 Jan 2018 12:44:43 +0100 Subject: [PATCH 8/8] Remove unnecessary id param in event name builder --- .../analytics/segment_event_name_builder.ex | 24 +++++++++---------- .../analytics/segment_plug_tracker.ex | 1 - lib/code_corps/analytics/segment_tracker.ex | 6 ++--- .../segment_event_name_builder_test.exs | 22 ++++++++--------- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/lib/code_corps/analytics/segment_event_name_builder.ex b/lib/code_corps/analytics/segment_event_name_builder.ex index b7be17e76..f94cb875b 100644 --- a/lib/code_corps/analytics/segment_event_name_builder.ex +++ b/lib/code_corps/analytics/segment_event_name_builder.ex @@ -3,27 +3,27 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilder do Used for building friendly event names for use in Segment tracking """ - @spec build(String.t, atom, struct) :: String.t - def build(id, action, record), do: get_event_name(id, action, record) + @spec build(atom, struct) :: String.t + def build(action, record), do: get_event_name(action, record) @actions_without_properties [:updated_profile, :signed_in, :signed_out, :signed_up] - defp get_event_name(_, action, _) when action in @actions_without_properties do + defp get_event_name(action, _) when action in @actions_without_properties do friendly_action_name(action) end - defp get_event_name(_, :update, %CodeCorps.DonationGoal{}) do + defp get_event_name(:update, %CodeCorps.DonationGoal{}) do "Updated Donation Goal" end - defp get_event_name(_, :payment_succeeded, %CodeCorps.StripeInvoice{}) do + defp get_event_name(:payment_succeeded, %CodeCorps.StripeInvoice{}) do "Processed Subscription Payment" end - defp get_event_name(_, :create, %CodeCorps.User{}), do: "Signed Up" - defp get_event_name(_, :update, %CodeCorps.User{}), do: "Updated Profile" - defp get_event_name(_, :create, %CodeCorps.UserCategory{}), do: "Added User Category" - defp get_event_name(_, :create, %CodeCorps.UserSkill{}), do: "Added User Skill" - defp get_event_name(_, :create, %CodeCorps.UserRole{}), do: "Added User Role" - defp get_event_name(_, :create, %{token: _, user_id: _}), do: "Signed In" - defp get_event_name(_, action, model) do + defp get_event_name(:create, %CodeCorps.User{}), do: "Signed Up" + defp get_event_name(:update, %CodeCorps.User{}), do: "Updated Profile" + defp get_event_name(:create, %CodeCorps.UserCategory{}), do: "Added User Category" + defp get_event_name(:create, %CodeCorps.UserSkill{}), do: "Added User Skill" + defp get_event_name(:create, %CodeCorps.UserRole{}), do: "Added User Role" + defp get_event_name(:create, %{token: _, user_id: _}), do: "Signed In" + defp get_event_name(action, model) do [friendly_action_name(action), friendly_model_name(model)] |> Enum.join(" ") end diff --git a/lib/code_corps/analytics/segment_plug_tracker.ex b/lib/code_corps/analytics/segment_plug_tracker.ex index 4bb88d1a4..d9dbc7545 100644 --- a/lib/code_corps/analytics/segment_plug_tracker.ex +++ b/lib/code_corps/analytics/segment_plug_tracker.ex @@ -19,7 +19,6 @@ defmodule CodeCorps.Analytics.SegmentPlugTracker do if successful? && SegmentTrackingSupport.includes?(action, resource) do user_id = SegmentDataExtractor.get_user_id(conn, resource) SegmentTracker.track(user_id, action, resource) - mark_tracked(conn) else mark_untracked(conn) diff --git a/lib/code_corps/analytics/segment_tracker.ex b/lib/code_corps/analytics/segment_tracker.ex index 1240e42a6..241592adb 100644 --- a/lib/code_corps/analytics/segment_tracker.ex +++ b/lib/code_corps/analytics/segment_tracker.ex @@ -22,10 +22,10 @@ defmodule CodeCorps.Analytics.SegmentTracker do Calls `track` in the configured API module. """ @spec track(String.t, atom | String.t, struct) :: any - def track(id, action, data) when is_atom(action) do - event = SegmentEventNameBuilder.build(id, action, data) + def track(user_id, action, data) when is_atom(action) do + event = SegmentEventNameBuilder.build(action, data) traits = SegmentTraitsBuilder.build(data) - @api.track(id, event, traits) + @api.track(user_id, event, traits) end def track(user_id, event, data) when is_binary(event) do traits = SegmentTraitsBuilder.build(data) diff --git a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs index 6f760aa40..a38eae821 100644 --- a/test/lib/code_corps/analytics/segment_event_name_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_event_name_builder_test.exs @@ -9,32 +9,32 @@ defmodule CodeCorps.Analytics.SegmentEventNameBuilderTest do describe "get_action_name/2" do test "with comment" do - assert SegmentEventNameBuilder.build("1", :create, build(:comment)) == "Created Comment" - assert SegmentEventNameBuilder.build("1", :update, build(:comment)) == "Edited Comment" + assert SegmentEventNameBuilder.build(:create, build(:comment)) == "Created Comment" + assert SegmentEventNameBuilder.build(:update, build(:comment)) == "Edited Comment" end test "with task" do - assert SegmentEventNameBuilder.build("1", :create, build(:task)) == "Created Task" - assert SegmentEventNameBuilder.build("1", :update, build(:task)) == "Edited Task" + assert SegmentEventNameBuilder.build(:create, build(:task)) == "Created Task" + assert SegmentEventNameBuilder.build(:update, build(:task)) == "Edited Task" end test "with user" do - assert SegmentEventNameBuilder.build("1", :create, build(:user)) == "Signed Up" + assert SegmentEventNameBuilder.build(:create, build(:user)) == "Signed Up" end test "with user category" do - assert SegmentEventNameBuilder.build("1", :create, build(:user_category)) == "Added User Category" - assert SegmentEventNameBuilder.build("1", :delete, build(:user_category)) == "Removed User Category" + assert SegmentEventNameBuilder.build(:create, build(:user_category)) == "Added User Category" + assert SegmentEventNameBuilder.build(:delete, build(:user_category)) == "Removed User Category" end test "with user role" do - assert SegmentEventNameBuilder.build("1", :create, build(:user_role)) == "Added User Role" - assert SegmentEventNameBuilder.build("1", :delete, build(:user_role)) == "Removed User Role" + assert SegmentEventNameBuilder.build(:create, build(:user_role)) == "Added User Role" + assert SegmentEventNameBuilder.build(:delete, build(:user_role)) == "Removed User Role" end test "with user skill" do - assert SegmentEventNameBuilder.build("1", :create, build(:user_skill)) == "Added User Skill" - assert SegmentEventNameBuilder.build("1", :delete, build(:user_skill)) == "Removed User Skill" + assert SegmentEventNameBuilder.build(:create, build(:user_skill)) == "Added User Skill" + assert SegmentEventNameBuilder.build(:delete, build(:user_skill)) == "Removed User Skill" end end end