teamdigitale/italia-app

View on GitHub
ts/features/services/common/analytics/index.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import { getType } from "typesafe-actions";
import { mixpanel, mixpanelTrack } from "../../../../mixpanel";
import { Action } from "../../../../store/actions/types";
import { buildEventProperties } from "../../../../utils/analytics";
import { getNetworkErrorMessage } from "../../../../utils/errors";
import { loadServicePreference } from "../../details/store/actions/preference";
import {
  featuredInstitutionsGet,
  featuredServicesGet,
  paginatedInstitutionsGet
} from "../../home/store/actions";
import { paginatedServicesGet } from "../../institution/store/actions";
import { searchPaginatedInstitutionsGet } from "../../search/store/actions";

type ServiceBaseType = {
  service_id: string;
  service_name: string;
} & InstitutionBaseType;

type InstitutionBaseType = {
  organization_name: string;
};

type ServiceDetailsType = {
  bottom_cta_available: boolean;
  organization_fiscal_code: string;
  service_category: "special" | "standard";
} & ServiceBaseType;

type ServiceDetailsConsentType = {
  is_special_service: boolean;
  main_consent_status: boolean;
  push_consent_status: boolean;
  read_confirmation_consent_status: boolean;
  service_id: string;
};

const ConsentTypeLabels = {
  inbox: "main",
  email: "email",
  push: "push",
  can_access_message_read_status: "read_confirmation"
} as const;

type ServiceConsentChangedType = {
  consent_type: keyof typeof ConsentTypeLabels;
  consent_status: boolean;
  service_id: string;
};

type ServiceDetailsUserExitType = {
  link: string;
  service_id: string;
};

type SpecialServiceStatusChangedType = {
  is_active: boolean;
  service_id: string;
};

type InstitutionDetailsType = {
  organization_fiscal_code: string;
  services_count: number;
} & InstitutionBaseType;

type ServiceSelectedType = {
  source: "featured_services" | "organization_detail";
} & ServiceBaseType;

type InstitutionSelectedType = {
  organization_fiscal_code: string;
  source:
    | "featured_organizations"
    | "main_list"
    | "search_list"
    | "recent_list";
} & InstitutionBaseType;

type SearchStartType = {
  source: "bottom_link" | "header_icon" | "search_bar";
};

export type CtaCategoryType = "custom_1" | "custom_2";

type ServiceDetailsCtaTappedType = {
  cta_category: CtaCategoryType;
  service_id: string;
};

export const trackServicesHome = () =>
  void mixpanelTrack("SERVICES", buildEventProperties("UX", "screen_view"));

export const trackServicesHomeError = (
  reason: string,
  source: "featured_services" | "featured_organizations" | "main_list"
) =>
  void mixpanelTrack(
    "SERVICES_ERROR",
    buildEventProperties("KO", undefined, { reason, source })
  );

export const trackInstitutionsScroll = () =>
  void mixpanelTrack("SERVICES_SCROLL", buildEventProperties("UX", "action"));

export const trackSearchStart = (props: SearchStartType) =>
  void mixpanelTrack(
    "SERVICES_SEARCH_START",
    buildEventProperties("UX", "action", props)
  );

export const trackServiceSelected = ({
  organization_name,
  service_id,
  service_name,
  source
}: ServiceSelectedType) =>
  void mixpanelTrack(
    "SERVICES_SELECTED",
    buildEventProperties("UX", "action", {
      organization_name,
      service_id,
      service_name,
      source
    })
  );

export const trackInstitutionSelected = ({
  organization_fiscal_code,
  organization_name,
  source
}: InstitutionSelectedType) =>
  void mixpanelTrack(
    "SERVICES_ORGANIZATION_SELECTED",
    buildEventProperties("UX", "action", {
      organization_fiscal_code,
      organization_name,
      source
    })
  );

export const trackInstitutionDetails = ({
  organization_fiscal_code,
  organization_name,
  services_count = 0
}: InstitutionDetailsType) =>
  void mixpanelTrack(
    "SERVICES_ORGANIZATION_DETAIL",
    buildEventProperties("UX", "screen_view", {
      organization_fiscal_code,
      organization_name,
      services_count
    })
  );

export const trackInstitutionDetailsError = (
  organization_fiscal_code: string,
  reason: string
) =>
  void mixpanelTrack(
    "SERVICES_ORGANIZATION_DETAIL_ERROR",
    buildEventProperties("KO", undefined, { organization_fiscal_code, reason })
  );

export const trackSearchPage = () =>
  void mixpanelTrack(
    "SERVICES_SEARCH_PAGE",
    buildEventProperties("UX", "screen_view")
  );

export const trackSearchInput = () =>
  void mixpanelTrack(
    "SERVICES_SEARCH_INPUT",
    buildEventProperties("UX", "action")
  );

export const trackSearchResult = (results_count: number = 0) =>
  void mixpanelTrack(
    "SERVICES_SEARCH_RESULT_PAGE",
    buildEventProperties("UX", "screen_view", { results_count })
  );

export const trackSearchResultScroll = () =>
  void mixpanelTrack(
    "SERVICES_SEARCH_RESULT_SCROLL",
    buildEventProperties("UX", "action")
  );

export const trackSearchError = (reason: string) =>
  void mixpanelTrack(
    "SERVICES_SEARCH_ERROR",
    buildEventProperties("KO", undefined, { reason })
  );

export const trackServiceDetails = (props: ServiceDetailsType) =>
  void mixpanelTrack(
    "SERVICES_DETAIL",
    buildEventProperties("UX", "screen_view", props)
  );

export const trackServiceDetailsConsent = (props: ServiceDetailsConsentType) =>
  void mixpanelTrack(
    "SERVICES_DETAIL_CONSENT",
    buildEventProperties("UX", "screen_view", props)
  );

export const trackServiceConsentChanged = ({
  consent_type,
  ...rest
}: ServiceConsentChangedType) =>
  void mixpanelTrack(
    "SERVICES_CONSENT_CHANGED",
    buildEventProperties("UX", "action", {
      ...rest,
      consent_type: ConsentTypeLabels[consent_type]
    })
  );

export const trackServiceDetailsUserExit = (
  props: ServiceDetailsUserExitType
) =>
  void mixpanelTrack(
    "SERVICES_DETAIL_USER_EXIT",
    buildEventProperties("UX", "exit", props)
  );

export const trackServicesCgnStartRequest = (service_id: string) =>
  void mixpanelTrack(
    "SERVICES_CGN_START_REQUEST",
    buildEventProperties("UX", "action", {
      service_id
    })
  );

export const trackSpecialServiceStatusChanged = (
  props: SpecialServiceStatusChangedType
) =>
  void mixpanelTrack(
    "SERVICES_SPECIAL_SERVICE_STATUS_CHANGED",
    buildEventProperties("UX", "action", props)
  );

export const trackServiceDetailsError = (service_id: string, reason: string) =>
  void mixpanelTrack(
    "SERVICES_DETAIL_ERROR",
    buildEventProperties("KO", undefined, { service_id, reason })
  );

export const trackServiceDetailsCtaTapped = (
  props: ServiceDetailsCtaTappedType
) =>
  void mixpanelTrack(
    "SERVICES_DETAIL_CTA_TAPPED",
    buildEventProperties("UX", "action", props)
  );

/**
 * Isolated tracker for services actions
 */
export const trackServicesAction =
  (_: NonNullable<typeof mixpanel>) =>
  (action: Action): void => {
    switch (action.type) {
      // Services home
      case getType(paginatedInstitutionsGet.failure):
        return trackServicesHomeError(
          getNetworkErrorMessage(action.payload),
          "main_list"
        );
      case getType(featuredServicesGet.failure):
        return trackServicesHomeError(
          getNetworkErrorMessage(action.payload),
          "featured_services"
        );
      case getType(featuredInstitutionsGet.failure):
        return trackServicesHomeError(
          getNetworkErrorMessage(action.payload),
          "featured_organizations"
        );
      // Search results
      case getType(searchPaginatedInstitutionsGet.success):
        return trackSearchResult(action.payload.count);
      case getType(searchPaginatedInstitutionsGet.failure):
        return trackSearchError(getNetworkErrorMessage(action.payload));
      // Institution details
      case getType(paginatedServicesGet.failure):
        return trackInstitutionDetailsError(
          action.payload.id,
          getNetworkErrorMessage(action.payload)
        );
      // Service details
      case getType(loadServicePreference.failure):
        return trackServiceDetailsError(
          action.payload.id,
          getNetworkErrorMessage(action.payload)
        );
    }
  };