Skip to content

Commit

Permalink
Refactor analytics reporting 📈
Browse files Browse the repository at this point in the history
  • Loading branch information
wotschofsky committed Dec 18, 2024
1 parent 6469f72 commit 14c3115
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 44 deletions.
17 changes: 9 additions & 8 deletions app/_components/feedback-prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { useLocalStorage } from '@uidotdev/usehooks';
import { XIcon } from 'lucide-react';
import ms from 'ms';
import { usePlausible } from 'next-plausible';
import { type FC, useCallback, useState } from 'react';

import { Button } from '@/components/ui/button';
Expand All @@ -16,11 +15,13 @@ import {
DialogTitle,
} from '@/components/ui/dialog';

import { useAnalytics } from '@/lib/analytics';

const INITIAL_DELAY = ms('10m');
const TIMEOUT_PERIOD = ms('7d');

export const FeedbackPrompt: FC = () => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const [lastDismissed, setLastDismissed] = useLocalStorage(
'feedback-prompt.last-dismissed',
Expand All @@ -36,19 +37,19 @@ export const FeedbackPrompt: FC = () => {
const handleNegative = useCallback(() => {
window.open('https://wotschofsky.com/#contact', '_blank');
handleDismiss();
plausible('Feedback: Negative');
}, [handleDismiss, plausible]);
reportEvent('Feedback: Negative', {});
}, [handleDismiss, reportEvent]);

const handleNeutral = useCallback(() => {
handleDismiss();
plausible('Feedback: Neutral');
}, [handleDismiss, plausible]);
reportEvent('Feedback: Neutral', {});
}, [handleDismiss, reportEvent]);

const handlePositive = useCallback(() => {
setDialogOpen(true);
handleDismiss();
plausible('Feedback: Positive');
}, [setDialogOpen, handleDismiss, plausible]);
reportEvent('Feedback: Positive', {});
}, [setDialogOpen, handleDismiss, reportEvent]);

return (
<>
Expand Down
20 changes: 9 additions & 11 deletions app/_components/search-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useDebounce, useMeasure } from '@uidotdev/usehooks';
import { SearchIcon } from 'lucide-react';
import { usePlausible } from 'next-plausible';
import { useParams, usePathname, useRouter } from 'next/navigation';
import { toASCII } from 'punycode';
import {
Expand All @@ -22,6 +21,7 @@ import { Card } from '@/components/ui/card';
import { Input } from '@/components/ui/input';

import { ClientOnly } from '@/components/client-only';
import { useAnalytics } from '@/lib/analytics';
import { EXAMPLE_DOMAINS } from '@/lib/data';
import {
cn,
Expand Down Expand Up @@ -120,7 +120,7 @@ type SearchFormProps = {
export const SearchForm: FC<SearchFormProps> = (props) => {
const isFirstRender = useFirstRender();

const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const router = useRouter();
const pathname = usePathname();
Expand Down Expand Up @@ -191,16 +191,16 @@ export const SearchForm: FC<SearchFormProps> = (props) => {
case 'domain':
setInvalid(false);
redirectUser(parsed.value);
plausible('Search Form: Submit', {
props: { domain: parsed.value },
reportEvent('Search Form: Submit', {
domain: parsed.value,
});
return;
case 'invalid':
setInvalid(true);
return;
}
},
[setInvalid, setIpDetailsOpen, redirectUser, plausible],
[setInvalid, setIpDetailsOpen, redirectUser, reportEvent],
);

const { suggestions } = useSuggestions(domain);
Expand All @@ -219,14 +219,12 @@ export const SearchForm: FC<SearchFormProps> = (props) => {
setSuggestionsVisible(false);
redirectUser(value);

plausible('Search Form: Click Suggestion', {
props: {
domain: value,
isExample: !domain,
},
reportEvent('Search Form: Click Suggestion', {
domain: value,
isExample: !domain,
});
},
[domain, setDomain, redirectUser, plausible],
[domain, setDomain, redirectUser, reportEvent],
);

const handleInput = useCallback<ChangeEventHandler<HTMLInputElement>>(
Expand Down
10 changes: 4 additions & 6 deletions app/lookup/[domain]/(dns)/_components/location-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { Label } from '@radix-ui/react-label';
import { usePlausible } from 'next-plausible';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { type FC, useCallback } from 'react';

Expand All @@ -13,6 +12,7 @@ import {
SelectValue,
} from '@/components/ui/select';

import { useAnalytics } from '@/lib/analytics';
import { REGIONS } from '@/lib/data';

type LocationSelectorProps = {
Expand All @@ -24,7 +24,7 @@ export const LocationSelector: FC<LocationSelectorProps> = ({
initialValue,
disabled,
}) => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const router = useRouter();
const pathname = usePathname();
Expand All @@ -43,11 +43,9 @@ export const LocationSelector: FC<LocationSelectorProps> = ({
const search = current.size ? `?${current.toString()}` : '';
router.push(`${pathname}${search}`);

plausible('Location Selector: Change', {
props: { location: value },
});
reportEvent('Location Selector: Change', { location: value });
},
[router, pathname, searchParams, plausible],
[router, pathname, searchParams, reportEvent],
);

return (
Expand Down
11 changes: 5 additions & 6 deletions app/lookup/[domain]/(dns)/_components/resolver-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { Label } from '@radix-ui/react-label';
import { usePlausible } from 'next-plausible';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { type FC, useCallback } from 'react';

Expand All @@ -13,14 +12,16 @@ import {
SelectValue,
} from '@/components/ui/select';

import { useAnalytics } from '@/lib/analytics';

type ResolverSelectorProps = {
initialValue?: string;
};

export const ResolverSelector: FC<ResolverSelectorProps> = ({
initialValue,
}) => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const router = useRouter();
const pathname = usePathname();
Expand All @@ -39,11 +40,9 @@ export const ResolverSelector: FC<ResolverSelectorProps> = ({
const search = current.size ? `?${current.toString()}` : '';
router.push(`${pathname}${search}`);

plausible('Resolver Selector: Change', {
props: { resolver: value },
});
reportEvent('Resolver Selector: Change', { resolver: value });
},
[router, pathname, searchParams, plausible],
[router, pathname, searchParams, reportEvent],
);

return (
Expand Down
9 changes: 5 additions & 4 deletions app/lookup/[domain]/_components/copy-button.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { CheckIcon, ClipboardIcon } from 'lucide-react';
import { usePlausible } from 'next-plausible';
import { type FC, useCallback, useState } from 'react';
import { toast } from 'sonner';

Expand All @@ -12,12 +11,14 @@ import {
TooltipTrigger,
} from '@/components/ui/tooltip';

import { useAnalytics } from '@/lib/analytics';

type CopyButton = {
value: string;
};

export const CopyButton: FC<CopyButton> = ({ value }) => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const [wasCopied, setWasCopied] = useState(false);
const copy = useCallback(() => {
Expand All @@ -27,8 +28,8 @@ export const CopyButton: FC<CopyButton> = ({ value }) => {

toast('Copied to clipboard');

plausible('Copy Button: Click', { props: { value } });
}, [value, setWasCopied, plausible]);
reportEvent('Copy Button: Click', { value });
}, [value, setWasCopied, reportEvent]);

if (wasCopied) {
return <CheckIcon className="mx-1 inline-block h-4 w-4 -translate-y-0.5" />;
Expand Down
9 changes: 5 additions & 4 deletions app/lookup/[domain]/_components/ip-link.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { InfoIcon } from 'lucide-react';
import { usePlausible } from 'next-plausible';
import { type FC, useCallback, useState } from 'react';

import {
Expand All @@ -11,20 +10,22 @@ import {
TooltipTrigger,
} from '@/components/ui/tooltip';

import { useAnalytics } from '@/lib/analytics';

import { IpDetailsModal } from './ip-details-modal';

type IpLinkProps = {
value: string;
};

export const IpLink: FC<IpLinkProps> = ({ value }) => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const [isOpen, setOpen] = useState(false);
const open = useCallback(() => {
setOpen(true);
plausible('IP Details: Open', { props: { ip: value } });
}, [setOpen, plausible, value]);
reportEvent('IP Details: Open', { ip: value });
}, [setOpen, reportEvent, value]);

return (
<>
Expand Down
11 changes: 6 additions & 5 deletions app/lookup/[domain]/_components/share-button.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use client';

import { Share2Icon } from 'lucide-react';
import { usePlausible } from 'next-plausible';
import { type FC, useCallback } from 'react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';

import { useAnalytics } from '@/lib/analytics';

export const ShareButton: FC = () => {
const plausible = usePlausible();
const { reportEvent } = useAnalytics();

const onClick = useCallback(() => {
if ('share' in navigator) {
Expand All @@ -22,10 +23,10 @@ export const ShareButton: FC = () => {
toast('Copied to clipboard');
}

plausible('Share: Click', {
props: { url: window.location.pathname + window.location.search },
reportEvent('Share: Click', {
url: window.location.pathname + window.location.search,
});
}, [plausible]);
}, [reportEvent]);

return (
<Button
Expand Down
40 changes: 40 additions & 0 deletions lib/analytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { usePlausible } from 'next-plausible';
import { useCallback, useMemo } from 'react';

type EmptyEvent = Record<string, never>;

type Events = {
'Copy Button: Click': { value: string };
'Feedback: Negative': EmptyEvent;
'Feedback: Neutral': EmptyEvent;
'Feedback: Positive': EmptyEvent;
'IP Details: Open': { ip: string };
'Location Selector: Change': { location: string };
'Outbound Link: Click': { url: string };
'Resolver Selector: Change': { resolver: string };
'Search Form: Click Suggestion': { domain: string; isExample: boolean };
'Search Form: Submit': { domain: string };
'Share: Click': { url: string };
'Star Reminder: Click': EmptyEvent;
'Star Reminder: Show': EmptyEvent;
'Star Reminder: Suppress': EmptyEvent;
'Trace: Click': { type: string; domain: string };
};

export const useAnalytics = () => {
const plausible = usePlausible();

const reportEvent = useCallback(
<T extends keyof Events>(event: T, props: Events[T]) => {
plausible(event, { props });
},
[plausible],
);

return useMemo(
() => ({
reportEvent,
}),
[reportEvent],
);
};

0 comments on commit 14c3115

Please sign in to comment.