Skip to content

Commit

Permalink
feat: added mixpanel events (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pritish Budhiraja authored Jan 3, 2024
1 parent 95a1d81 commit 543e074
Show file tree
Hide file tree
Showing 15 changed files with 72 additions and 27 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
apiBaseUrl=https://sandbox.hyperswitch.io
sdkBaseUrl=https://beta.hyperswitch.io/v1/HyperLoader.js
sdkBaseUrl=https://beta.hyperswitch.io/v1/HyperLoader.js
mixpanelToken=
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Follow these simple steps to set up Hyperswitch on your local machine.
```bash
apiBaseUrl = your-backend-url
sdkBaseUrl = your-sdk-url
mixpanelToken = mixpanel-token
# To view Mixpanel events on the Mixpanel dashboard, you must add your Mixpanel token; otherwise, you can ignore this requirement.
```

5. Start the ReScript compiler:
Expand Down
8 changes: 7 additions & 1 deletion src/entryPoints/hyperswitch/SidebarValues.res
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ open SidebarTypes
module GetProductionAccess = {
@react.component
let make = () => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let textStyles = HSwitchUtils.getTextClass(~textVariant=P2, ~paragraphTextVariant=Medium, ())
let {isProdIntentCompleted, setShowProdIntentForm} = React.useContext(
GlobalProvider.defaultContext,
Expand All @@ -18,7 +19,12 @@ module GetProductionAccess = {
<div
className={`flex items-center gap-2 ${backgroundColor} ${cursorStyles} px-4 py-3 m-2 ml-2 mb-3 !mx-4 whitespace-nowrap rounded`}
onClick={_ => {
isProdIntentCompleted ? () : setShowProdIntentForm(_ => true)
isProdIntentCompleted
? ()
: {
setShowProdIntentForm(_ => true)
mixpanelEvent(~eventName="get_production_access", ())
}
}}>
<div className={`text-white ${textStyles} !font-semibold`}>
{productionAccessString->React.string}
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/Window.res
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,6 @@ external fcWidget: 'a = "fcWidget"
type boundingClient = {x: int, y: int, width: int, height: int}
@send external getBoundingClientRect: Dom.element => boundingClient = "getBoundingClientRect"

type env = {apiBaseUrl?: string, sdkBaseUrl?: string}
type env = {apiBaseUrl?: string, sdkBaseUrl?: string, mixpanelToken?: string}
@val @scope("window")
external env: env = "_env_"
2 changes: 2 additions & 0 deletions src/screens/HyperSwitch/Analytics/GenerateReport.res
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@react.component
let make = (~entityName) => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let (reportModal, setReportModal) = React.useState(_ => false)

<>
Expand All @@ -8,6 +9,7 @@ let make = (~entityName) => {
buttonType={Primary}
onClick={_ => {
setReportModal(_ => true)
mixpanelEvent(~eventName="generate_reports", ())
}}
/>
<UIUtils.RenderIf condition={reportModal}>
Expand Down
2 changes: 2 additions & 0 deletions src/screens/HyperSwitch/Developer/APIKeys/KeyManagement.res
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ module ApiKeyAddBtn = {
open DeveloperUtils
@react.component
let make = (~getAPIKeyDetails) => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let (showModal, setShowModal) = React.useState(_ => false)
let initialValues = Js.Dict.empty()
initialValues->Js.Dict.set("expiration", Never->getStringFromRecordType->Js.Json.string)
Expand All @@ -192,6 +193,7 @@ module ApiKeyAddBtn = {
buttonType=Secondary
buttonSize=Small
onClick={_ => {
mixpanelEvent(~eventName="create_new_api_key", ())
setShowModal(_ => true)
}}
/>
Expand Down
5 changes: 5 additions & 0 deletions src/screens/HyperSwitch/Home/HomeUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ module CheckoutCard = {
let make = () => {
let fetchApi = AuthHooks.useApiFetcher()
let showPopUp = PopUpState.useShowPopUp()
let mixpanelEvent = MixpanelHook.useSendEvent()
let (_authStatus, setAuthStatus) = React.useContext(AuthInfoProvider.authStatusContext)
let {setIsSidebarExpanded} = React.useContext(SidebarProvider.defaultContext)
let isPlayground = HSLocalStorage.getIsPlaygroundFromLocalStorage()
Expand Down Expand Up @@ -179,6 +180,7 @@ module CheckoutCard = {
},
})
} else {
mixpanelEvent(~eventName=`try_test_payment`, ())
RescriptReactRouter.replace("/sdk")
}
}
Expand Down Expand Up @@ -268,6 +270,7 @@ module ControlCenter = {
module DevResources = {
@react.component
let make = () => {
let mixpanelEvent = MixpanelHook.useSendEvent()
<div className="mb-5">
<PageHeading
title="Developer resources"
Expand All @@ -286,6 +289,7 @@ module DevResources = {
buttonType={Secondary}
buttonSize={Small}
onClick={_ => {
mixpanelEvent(~eventName=`dev_docs`, ())
"https://hyperswitch.io/docs"->Window._open
}}
/>
Expand All @@ -303,6 +307,7 @@ module DevResources = {
buttonType={Secondary}
buttonSize={Small}
onClick={_ => {
mixpanelEvent(~eventName=`contribute_in_open_source`, ())
"https://github.com/juspay/hyperswitch"->Window._open
}}
/>
Expand Down
25 changes: 23 additions & 2 deletions src/screens/HyperSwitch/Home/HomeV2.res
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ module QuickStart = {
)
let usePostEnumDetails = EnumVariantHook.usePostEnumDetails()
let updateEnumInRecoil = EnumVariantHook.useUpdateEnumInRecoil()
let mixpanelEvent = MixpanelHook.useSendEvent()
let (configureButtonState, setConfigureButtonState) = React.useState(_ => Button.Normal)
let connectorList =
HyperswitchAtom.connectorListAtom->Recoil.useRecoilValueFromAtom->LogicUtils.safeParse
Expand Down Expand Up @@ -170,6 +171,15 @@ module QuickStart = {
"Get Production access"
}

let mixpanelEventForQuickStart = () =>
if !(typedValueOfEnum.testPayment.payment_id->Js.String2.length > 0) {
mixpanelEvent(~eventName=`quickstart_configure_test_mode`, ())
} else if !typedValueOfEnum.integrationCompleted {
mixpanelEvent(~eventName=`quickstart_start_integration_on_app`, ())
} else {
mixpanelEvent(~eventName=`quickstart_get_productuion_access`, ())
}

<div className="flex flex-col md:flex-row pt-10 border rounded-md bg-white gap-4">
<div className="flex flex-col justify-evenly gap-8 pl-10 pb-10 pr-2 md:pr-0">
<div className="flex flex-col gap-2">
Expand All @@ -192,6 +202,7 @@ module QuickStart = {
/>,
)}
onClick={_ => {
mixpanelEventForQuickStart()
setEnumsForPreviouslyConnectedConnectors()->ignore
}}
/>
Expand All @@ -208,6 +219,7 @@ module QuickStart = {
module RecipesAndPlugins = {
@react.component
let make = () => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let enumDetails =
HyperswitchAtom.enumVariantAtom
->Recoil.useRecoilValueFromAtom
Expand All @@ -221,7 +233,10 @@ module RecipesAndPlugins = {
<div className="grid grid-cols-1 md:grid-cols-2 w-full gap-4">
<div
className={boxCssHover(~ishoverStyleRequired=!isStripePlusPayPalCompleted, ())}
onClick={_ => RescriptReactRouter.push("stripe-plus-paypal")}>
onClick={_ => {
mixpanelEvent(~eventName=`stripe_plus_paypal`, ())
RescriptReactRouter.push("stripe-plus-paypal")
}}>
<div className="flex items-center gap-2">
<p className=cardHeaderTextStyle> {"Use PayPal with Stripe"->React.string} </p>
<Icon
Expand All @@ -244,7 +259,10 @@ module RecipesAndPlugins = {
</div>
<div
className={boxCssHover(~ishoverStyleRequired=!isWooCommercePalCompleted, ())}
onClick={_ => RescriptReactRouter.push("woocommerce")}>
onClick={_ => {
mixpanelEvent(~eventName=`woocommerce`, ())
RescriptReactRouter.push("woocommerce")
}}>
<div className="flex items-center gap-2">
<p className=cardHeaderTextStyle> {"WooCommerce plugin"->React.string} </p>
<Icon
Expand Down Expand Up @@ -273,6 +291,7 @@ module RecipesAndPlugins = {
module Resources = {
@react.component
let make = () => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let elements: array<HomeUtils.resourcesTypes> = [
{
id: "tryTheDemo",
Expand Down Expand Up @@ -307,8 +326,10 @@ module Resources = {
key={index->string_of_int}
onClick={_ => {
if item.id === "openSource" {
mixpanelEvent(~eventName=`contribute_in_open_source`, ())
"https://github.com/juspay/hyperswitch"->Window._open
} else if item.id === "developerdocs" {
mixpanelEvent(~eventName=`dev_docs`, ())
"https://hyperswitch.io/docs"->Window._open
} else if item.id === "tryTheDemo" {
RescriptReactRouter.replace("/sdk")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ let useSendEvent = () => {
open HSLocalStorage
open Window
let fetchApi = AuthHooks.useApiFetcher()
let url = RescriptReactRouter.useUrl()
let name = getFromUserDetails("name")
let deviceId = switch LocalStorage.getItem("deviceid")->Js.Nullable.toOption {
| Some(id) => id
| None => getFromUserDetails("email")
}
let currentUrl = `${hyperSwitchFEPrefix}/${url.path->Js.List.hd->Belt.Option.getWithDefault("")}`

let parseEmail = email => {
email->Js.String.length == 0 ? getFromMerchantDetails("email") : email
Expand All @@ -31,7 +29,7 @@ let useSendEvent = () => {
| Local => "localhost"
}

let trackApi = async (~email, ~merchantId, ~description, ~requestId, ~statusCode, ~event) => {
let trackApi = async (~email, ~merchantId, ~description, ~event) => {
let body = {
"event": event,
"properties": {
Expand All @@ -47,9 +45,6 @@ let useSendEvent = () => {
"merchantId": merchantId,
"environment": environment,
"description": description,
"x-request-id": requestId,
"responseStatusCode": statusCode,
"$current_url": currentUrl,
"lang": Navigator.browserLanguage,
"$os": Navigator.platform,
"$browser": Navigator.browserName,
Expand All @@ -71,10 +66,8 @@ let useSendEvent = () => {
}
}

(~eventName, ~email="", ~description=None, ~xRequestId=None, ~responseStatusCode=None, ()) => {
(~eventName, ~email="", ~description=None, ()) => {
let eventName = eventName->Js.String2.toLowerCase
let someRequestId = xRequestId->Belt.Option.getWithDefault("")
let someStatusCode = responseStatusCode->Belt.Option.getWithDefault(0)
let merchantId = getFromMerchantDetails("merchant_id")

if featureFlagDetails.mixPanel {
Expand All @@ -85,18 +78,9 @@ let useSendEvent = () => {
"merchantId": merchantId,
"environment": environment,
"description": description,
"x-request-id": someRequestId,
"responseStatusCode": someStatusCode,
},
)
trackApi(
~email={email->parseEmail},
~merchantId,
~description,
~requestId={someRequestId},
~statusCode={someStatusCode},
~event={eventName},
)->ignore
trackApi(~email={email->parseEmail}, ~merchantId, ~description, ~event={eventName})->ignore
}
}
}
2 changes: 2 additions & 0 deletions src/screens/HyperSwitch/Order/OrderUIUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ module GenerateSampleDataButton = {
open APIUtils
@react.component
let make = (~previewOnly, ~getOrdersList) => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let updateDetails = useUpdateMethod()
let showToast = ToastState.useShowToast()
let {sampleData} = HyperswitchAtom.featureFlagAtom->Recoil.useRecoilValueFromAtom

let generateSampleData = async () => {
mixpanelEvent(~eventName="generate_sample_data", ())
try {
let generateSampleDataUrl = getURL(~entityName=GENERATE_SAMPLE_DATA, ~methodType=Post, ())
let _ = await updateDetails(
Expand Down
3 changes: 3 additions & 0 deletions src/screens/HyperSwitch/Routing/ActiveRouting.res
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module TopRightIcons = {
module ActionButtons = {
@react.component
let make = (~routeType: routingType) => {
let mixpanelEvent = MixpanelHook.useSendEvent()
let showToast = ToastState.useShowToast()
let updateDetails = APIUtils.useUpdateMethod(~showErrorToast=false, ())

Expand Down Expand Up @@ -73,6 +74,7 @@ module ActionButtons = {
customButtonStyle="border !border-blue-700 bg-white !text-blue-700"
onClick={_ => {
RescriptReactRouter.push(`routing/${routingTypeName(routeType)}`)
mixpanelEvent(~eventName=`routing_setup_${routeType->routingTypeName}`, ())
}}
/>
| DEFAULTFALLBACK =>
Expand All @@ -83,6 +85,7 @@ module ActionButtons = {
buttonSize={Small}
onClick={_ => {
RescriptReactRouter.push(`routing/${routingTypeName(routeType)}`)
mixpanelEvent(~eventName=`routing_setup_${routeType->routingTypeName}`, ())
}}
/>

Expand Down
3 changes: 2 additions & 1 deletion src/screens/HyperSwitch/ThreeDSFlow/HSwitchThreeDS.res
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ let make = () => {
// Three Ds flow
open APIUtils
open ThreeDSUtils

let mixpanelEvent = MixpanelHook.useSendEvent()
let url = RescriptReactRouter.useUrl()
let fetchDetails = useGetMethod(~showErrorToast=false, ())
let updateDetails = useUpdateMethod(~showErrorToast=false, ())
Expand Down Expand Up @@ -237,6 +237,7 @@ let make = () => {
RescriptReactRouter.replace(`/3ds?type=new`)
}
let handleCreateNew = () => {
mixpanelEvent(~eventName="create_new_3ds_rule", ())
if showWarning {
showPopUp({
popUpType: (Warning, WithIcon),
Expand Down
6 changes: 5 additions & 1 deletion src/screens/HyperSwitch/UserManagement/UserRoleEntry.res
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ open UserRoleEntity
let make = () => {
open APIUtils
let fetchDetails = useGetMethod()
let mixpanelEvent = MixpanelHook.useSendEvent()
let (usersData, setUsersData) = React.useState(_ => [])
let (usersFilterData, setUsersFilterData) = React.useState(_ => [])
let (screenStateUsers, setScreenStateUsers) = React.useState(_ => PageLoaderWrapper.Loading)
Expand Down Expand Up @@ -126,7 +127,10 @@ let make = () => {
<Button
text={"Invite users"}
buttonType=Primary
onClick={_ => RescriptReactRouter.push("/users/invite-users")}
onClick={_ => {
mixpanelEvent(~eventName="invite_users", ())
RescriptReactRouter.push("/users/invite-users")
}}
customButtonStyle="w-48"
/>
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/screens/login/HSwitchLoginFlow/HyperSwitchAuth.res
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ let make = (~setAuthStatus: HyperSwitchAuthTypes.authStatus => unit, ~authType,
open LogicUtils

let url = RescriptReactRouter.useUrl()
let mixpanelEvent = MixpanelHook.useSendEvent()
let initialValues = Js.Dict.empty()->Js.Json.object_
let clientCountry = HSwitchUtils.getBrowswerDetails().clientCountry
let country = clientCountry.isoAlpha2->CountryUtils.getCountryCodeStringFromVarient
Expand Down Expand Up @@ -112,12 +113,23 @@ let make = (~setAuthStatus: HyperSwitchAuthTypes.authStatus => unit, ~authType,
Js.Nullable.null
}

let logMixpanelEvents = _ => {
open HyperSwitchAuthTypes
switch authType {
| LoginWithPassword => mixpanelEvent(~eventName=`signin_using_email&password`, ())
| LoginWithEmail => mixpanelEvent(~eventName=`signin_using_magic_link`, ())
| SignUP => mixpanelEvent(~eventName=`signup_using_magic_link`, ())
| _ => ()
}
}

let onSubmit = async (values, _) => {
try {
open HyperSwitchAuthTypes
let valuesDict = values->getDictFromJsonObject
let email = valuesDict->getString("email", "")
setEmail(_ => email)
logMixpanelEvents()

let _ = await (
switch (isMagicLinkEnabled, authType) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/HSwitchGlobalVars.res
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@val external appVersion: string = "appVersion"

let mixpanelToken = "" // add your mixpanel token here
let mixpanelToken = Window.env.mixpanelToken->Belt.Option.getWithDefault("mixpanel-token")

type hostType = Live | Sandbox | Local | Netlify

Expand Down

0 comments on commit 543e074

Please sign in to comment.