mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-13 20:54:16 +02:00
Add UTM registration tracking
This commit is contained in:
@@ -4,6 +4,7 @@ import Cookies from 'js-cookie';
|
|||||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||||
import { httpGet } from '../../lib/http';
|
import { httpGet } from '../../lib/http';
|
||||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||||
|
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||||
|
|
||||||
type GitHubButtonProps = {
|
type GitHubButtonProps = {
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
@@ -46,6 +47,8 @@ export function GitHubButton(props: GitHubButtonProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerUtmRegistration();
|
||||||
|
|
||||||
let redirectUrl = '/';
|
let redirectUrl = '/';
|
||||||
const gitHubRedirectAt = localStorage.getItem(GITHUB_REDIRECT_AT);
|
const gitHubRedirectAt = localStorage.getItem(GITHUB_REDIRECT_AT);
|
||||||
const lastPageBeforeGithub = localStorage.getItem(GITHUB_LAST_PAGE);
|
const lastPageBeforeGithub = localStorage.getItem(GITHUB_LAST_PAGE);
|
||||||
|
@@ -4,6 +4,10 @@ import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
|||||||
import { httpGet } from '../../lib/http';
|
import { httpGet } from '../../lib/http';
|
||||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||||
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
||||||
|
import {
|
||||||
|
getStoredUtmParams,
|
||||||
|
triggerUtmRegistration,
|
||||||
|
} from '../../lib/browser.ts';
|
||||||
|
|
||||||
type GoogleButtonProps = {
|
type GoogleButtonProps = {
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
@@ -37,6 +41,8 @@ export function GoogleButton(props: GoogleButtonProps) {
|
|||||||
}`,
|
}`,
|
||||||
)
|
)
|
||||||
.then(({ response, error }) => {
|
.then(({ response, error }) => {
|
||||||
|
const utmParams = getStoredUtmParams();
|
||||||
|
|
||||||
if (!response?.token) {
|
if (!response?.token) {
|
||||||
setError(error?.message || 'Something went wrong.');
|
setError(error?.message || 'Something went wrong.');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -45,6 +51,8 @@ export function GoogleButton(props: GoogleButtonProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerUtmRegistration();
|
||||||
|
|
||||||
let redirectUrl = '/';
|
let redirectUrl = '/';
|
||||||
const googleRedirectAt = localStorage.getItem(GOOGLE_REDIRECT_AT);
|
const googleRedirectAt = localStorage.getItem(GOOGLE_REDIRECT_AT);
|
||||||
const lastPageBeforeGoogle = localStorage.getItem(GOOGLE_LAST_PAGE);
|
const lastPageBeforeGoogle = localStorage.getItem(GOOGLE_LAST_PAGE);
|
||||||
@@ -97,9 +105,12 @@ export function GoogleButton(props: GoogleButtonProps) {
|
|||||||
// For non authentication pages, we want to redirect back to the page
|
// For non authentication pages, we want to redirect back to the page
|
||||||
// the user was on before they clicked the social login button
|
// the user was on before they clicked the social login button
|
||||||
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
||||||
const pagePath = ['/respond-invite', '/befriend', '/r', '/ai'].includes(
|
const pagePath = [
|
||||||
window.location.pathname,
|
'/respond-invite',
|
||||||
)
|
'/befriend',
|
||||||
|
'/r',
|
||||||
|
'/ai',
|
||||||
|
].includes(window.location.pathname)
|
||||||
? window.location.pathname + window.location.search
|
? window.location.pathname + window.location.search
|
||||||
: window.location.pathname;
|
: window.location.pathname;
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
|||||||
import { httpGet } from '../../lib/http';
|
import { httpGet } from '../../lib/http';
|
||||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||||
import { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';
|
import { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';
|
||||||
|
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||||
|
|
||||||
type LinkedInButtonProps = {
|
type LinkedInButtonProps = {
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
@@ -45,6 +46,8 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerUtmRegistration();
|
||||||
|
|
||||||
let redirectUrl = '/';
|
let redirectUrl = '/';
|
||||||
const linkedInRedirectAt = localStorage.getItem(LINKEDIN_REDIRECT_AT);
|
const linkedInRedirectAt = localStorage.getItem(LINKEDIN_REDIRECT_AT);
|
||||||
const lastPageBeforeLinkedIn = localStorage.getItem(LINKEDIN_LAST_PAGE);
|
const lastPageBeforeLinkedIn = localStorage.getItem(LINKEDIN_LAST_PAGE);
|
||||||
@@ -97,9 +100,12 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
|||||||
// For non authentication pages, we want to redirect back to the page
|
// For non authentication pages, we want to redirect back to the page
|
||||||
// the user was on before they clicked the social login button
|
// the user was on before they clicked the social login button
|
||||||
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
if (!['/login', '/signup'].includes(window.location.pathname)) {
|
||||||
const pagePath = ['/respond-invite', '/befriend', '/r', '/ai'].includes(
|
const pagePath = [
|
||||||
window.location.pathname,
|
'/respond-invite',
|
||||||
)
|
'/befriend',
|
||||||
|
'/r',
|
||||||
|
'/ai',
|
||||||
|
].includes(window.location.pathname)
|
||||||
? window.location.pathname + window.location.search
|
? window.location.pathname + window.location.search
|
||||||
: window.location.pathname;
|
: window.location.pathname;
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ import { httpPost } from '../../lib/http';
|
|||||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||||
import { Spinner } from '../ReactIcons/Spinner';
|
import { Spinner } from '../ReactIcons/Spinner';
|
||||||
import { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';
|
import { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';
|
||||||
|
import { triggerUtmRegistration } from '../../lib/browser.ts';
|
||||||
|
|
||||||
export function TriggerVerifyAccount() {
|
export function TriggerVerifyAccount() {
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -26,6 +27,8 @@ export function TriggerVerifyAccount() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerUtmRegistration();
|
||||||
|
|
||||||
setAuthToken(response.token);
|
setAuthToken(response.token);
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
})
|
})
|
||||||
|
@@ -6,6 +6,7 @@ import { X } from 'lucide-react';
|
|||||||
import { setViewSponsorCookie } from '../lib/jwt';
|
import { setViewSponsorCookie } from '../lib/jwt';
|
||||||
import { isMobile } from '../lib/is-mobile';
|
import { isMobile } from '../lib/is-mobile';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
import { getUrlUtmParams } from '../lib/browser.ts';
|
||||||
|
|
||||||
export type PageSponsorType = {
|
export type PageSponsorType = {
|
||||||
company: string;
|
company: string;
|
||||||
@@ -50,6 +51,16 @@ export function PageSponsor(props: PageSponsorProps) {
|
|||||||
const [sponsorId, setSponsorId] = useState<string | null>(null);
|
const [sponsorId, setSponsorId] = useState<string | null>(null);
|
||||||
const [sponsor, setSponsor] = useState<PageSponsorType>();
|
const [sponsor, setSponsor] = useState<PageSponsorType>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const foundUtmParams = getUrlUtmParams();
|
||||||
|
|
||||||
|
if (!foundUtmParams.utmSource) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem('utm_params', JSON.stringify(foundUtmParams));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const loadSponsor = async () => {
|
const loadSponsor = async () => {
|
||||||
const currentPath = window.location.pathname;
|
const currentPath = window.location.pathname;
|
||||||
if (
|
if (
|
||||||
|
@@ -1,3 +1,65 @@
|
|||||||
|
type UtmParams = Partial<{
|
||||||
|
utmSource: string;
|
||||||
|
utmMedium: string;
|
||||||
|
utmCampaign: string;
|
||||||
|
utmContent: string;
|
||||||
|
utmTerm: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export function getUrlUtmParams(): UtmParams {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const utmParams = new URLSearchParams(window.location.search);
|
||||||
|
const utmSource = utmParams.get('utm_source') ?? undefined;
|
||||||
|
const utmMedium = utmParams.get('utm_medium') ?? undefined;
|
||||||
|
const utmCampaign = utmParams.get('utm_campaign') ?? undefined;
|
||||||
|
const utmContent = utmParams.get('utm_content') ?? undefined;
|
||||||
|
const utmTerm = utmParams.get('utm_term') ?? undefined;
|
||||||
|
|
||||||
|
if (!utmSource || !utmCampaign) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
utmSource: utmCampaign ? utmSource.toLowerCase() : undefined,
|
||||||
|
utmMedium: utmMedium ? utmMedium.toLowerCase() : undefined,
|
||||||
|
utmCampaign: utmCampaign ? utmCampaign.toLowerCase() : undefined,
|
||||||
|
utmContent: utmContent ? utmContent.toLowerCase() : undefined,
|
||||||
|
utmTerm: utmTerm ? utmTerm.toLowerCase() : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function triggerUtmRegistration() {
|
||||||
|
const utmParams = getStoredUtmParams();
|
||||||
|
console.log(utmParams);
|
||||||
|
if (!utmParams.utmSource) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.removeItem('utm_params');
|
||||||
|
|
||||||
|
window.fireEvent({
|
||||||
|
category: 'UserRegistration',
|
||||||
|
action: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,
|
||||||
|
label: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStoredUtmParams(): UtmParams {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const utmParams = localStorage.getItem('utm_params');
|
||||||
|
if (!utmParams) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(utmParams);
|
||||||
|
}
|
||||||
|
|
||||||
export function getUrlParams() {
|
export function getUrlParams() {
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
return {};
|
return {};
|
||||||
|
Reference in New Issue
Block a user