mirror of
https://github.com/uetchy/namae.git
synced 2025-03-17 12:30:32 +09:00
chore: add ga events
This commit is contained in:
parent
0fa08f57f3
commit
769548ccc9
@ -33,25 +33,6 @@ export default function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Search() {
|
|
||||||
const params = useParams<{query: string}>();
|
|
||||||
const currentQuery = sanitize(params.query);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Helmet>
|
|
||||||
<title>Search for "{currentQuery}" — namae</title>
|
|
||||||
</Helmet>
|
|
||||||
<Header>
|
|
||||||
<Form initialValue={currentQuery} />
|
|
||||||
</Header>
|
|
||||||
<Content>
|
|
||||||
<Cards query={currentQuery} />
|
|
||||||
</Content>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
@ -70,6 +51,25 @@ function Home() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Search() {
|
||||||
|
const {query} = useParams<{query: string}>();
|
||||||
|
const currentQuery = sanitize(query);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Helmet>
|
||||||
|
<title>Search for "{currentQuery}" — namae</title>
|
||||||
|
</Helmet>
|
||||||
|
<Header>
|
||||||
|
<Form initialValue={currentQuery} />
|
||||||
|
</Header>
|
||||||
|
<Content>
|
||||||
|
<Cards query={currentQuery} />
|
||||||
|
</Content>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const GlobalStyle = createGlobalStyle`
|
const GlobalStyle = createGlobalStyle`
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -3,7 +3,7 @@ import styled from 'styled-components';
|
|||||||
import {useTranslation} from 'react-i18next';
|
import {useTranslation} from 'react-i18next';
|
||||||
import {Link, useHistory} from 'react-router-dom';
|
import {Link, useHistory} from 'react-router-dom';
|
||||||
import {sanitize} from '../util/text';
|
import {sanitize} from '../util/text';
|
||||||
import {sendQueryStatistics} from '../util/analytics';
|
import {sendQueryEvent} from '../util/analytics';
|
||||||
import {useDeferredState} from '../util/hooks';
|
import {useDeferredState} from '../util/hooks';
|
||||||
import {mobile} from '../util/css';
|
import {mobile} from '../util/css';
|
||||||
import Suggestion from './Suggestion';
|
import Suggestion from './Suggestion';
|
||||||
@ -44,7 +44,7 @@ const Form: React.FC<{
|
|||||||
if (!query || query === '') {
|
if (!query || query === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendQueryStatistics(query.length);
|
sendQueryEvent(query);
|
||||||
history.push(`/s/${query}`);
|
history.push(`/s/${query}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,10 @@ import {capitalize, stem, germanify, njoin, lower, upper} from '../util/text';
|
|||||||
import {sampleFromArray, fillArray} from '../util/array';
|
import {sampleFromArray, fillArray} from '../util/array';
|
||||||
import {mobile} from '../util/css';
|
import {mobile} from '../util/css';
|
||||||
import {sanitize} from '../util/text';
|
import {sanitize} from '../util/text';
|
||||||
|
import {
|
||||||
|
sendShuffleSuggestionEvent,
|
||||||
|
sendAcceptSuggestionEvent,
|
||||||
|
} from '../util/analytics';
|
||||||
|
|
||||||
type Modifier = (word: string) => string;
|
type Modifier = (word: string) => string;
|
||||||
|
|
||||||
@ -22,6 +26,7 @@ const modifiers: Modifier[] = [
|
|||||||
(word): string => njoin('Co', lower(word), {elision: false}),
|
(word): string => njoin('Co', lower(word), {elision: false}),
|
||||||
(word): string => njoin('Deep', capitalize(word), {elision: false}),
|
(word): string => njoin('Deep', capitalize(word), {elision: false}),
|
||||||
(word): string => njoin('Easy', capitalize(word), {elision: false}),
|
(word): string => njoin('Easy', capitalize(word), {elision: false}),
|
||||||
|
(word): string => njoin('En', lower(word), {elision: false}),
|
||||||
(word): string => njoin('Fast', lower(word), {elision: false}),
|
(word): string => njoin('Fast', lower(word), {elision: false}),
|
||||||
(word): string => njoin('Fire', lower(word), {elision: false}),
|
(word): string => njoin('Fire', lower(word), {elision: false}),
|
||||||
(word): string => njoin('Fusion', capitalize(word), {elision: false}),
|
(word): string => njoin('Fusion', capitalize(word), {elision: false}),
|
||||||
@ -98,6 +103,7 @@ const modifiers: Modifier[] = [
|
|||||||
(word): string => njoin(capitalize(word), 'Club', {elision: false}),
|
(word): string => njoin(capitalize(word), 'Club', {elision: false}),
|
||||||
(word): string => njoin(capitalize(word), 'DB', {elision: false}),
|
(word): string => njoin(capitalize(word), 'DB', {elision: false}),
|
||||||
(word): string => njoin(capitalize(word), 'Express', {elision: false}),
|
(word): string => njoin(capitalize(word), 'Express', {elision: false}),
|
||||||
|
(word): string => njoin(capitalize(word), 'en'),
|
||||||
(word): string => njoin(capitalize(word), 'feed', {elision: false}),
|
(word): string => njoin(capitalize(word), 'feed', {elision: false}),
|
||||||
(word): string => njoin(capitalize(word), 'Finder', {elision: false}),
|
(word): string => njoin(capitalize(word), 'Finder', {elision: false}),
|
||||||
(word): string => njoin(capitalize(word), 'flow', {elision: false}),
|
(word): string => njoin(capitalize(word), 'flow', {elision: false}),
|
||||||
@ -186,9 +192,15 @@ const Suggestion: React.FC<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyQuery(name: string): void {
|
function applyQuery(name: string): void {
|
||||||
|
sendAcceptSuggestionEvent();
|
||||||
onSubmit(name);
|
onSubmit(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onShuffleButtonClicked() {
|
||||||
|
sendShuffleSuggestionEvent();
|
||||||
|
shuffle();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isEffective = true;
|
let isEffective = true;
|
||||||
const fn = async (): Promise<void> => {
|
const fn = async (): Promise<void> => {
|
||||||
@ -218,7 +230,7 @@ const Suggestion: React.FC<{
|
|||||||
</Item>
|
</Item>
|
||||||
))}
|
))}
|
||||||
</Items>
|
</Items>
|
||||||
<Button onClick={shuffle}>
|
<Button onClick={onShuffleButtonClicked}>
|
||||||
<TiArrowSync />
|
<TiArrowSync />
|
||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -24,6 +24,7 @@ import {DiRust, DiHeroku} from 'react-icons/di';
|
|||||||
import {SpectrumIcon, NowIcon, NetlifyIcon, OcamlIcon} from './Icons';
|
import {SpectrumIcon, NowIcon, NetlifyIcon, OcamlIcon} from './Icons';
|
||||||
import {shuffleArray} from '../util/array';
|
import {shuffleArray} from '../util/array';
|
||||||
import {mobile} from '../util/css';
|
import {mobile} from '../util/css';
|
||||||
|
import {sendExampleQueryEvent} from '../util/analytics';
|
||||||
|
|
||||||
const QUERY_WORDS = [
|
const QUERY_WORDS = [
|
||||||
'Name',
|
'Name',
|
||||||
@ -54,7 +55,11 @@ const Welcome: React.FC = () => {
|
|||||||
<List>
|
<List>
|
||||||
{queries.map((query) => (
|
{queries.map((query) => (
|
||||||
<ListButton key={query}>
|
<ListButton key={query}>
|
||||||
<Link to={`/s/${query}`}>{query}</Link>
|
<Link
|
||||||
|
to={`/s/${query}`}
|
||||||
|
onClick={() => sendExampleQueryEvent(query)}>
|
||||||
|
{query}
|
||||||
|
</Link>
|
||||||
</ListButton>
|
</ListButton>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
@ -7,7 +7,7 @@ import BarLoader from 'react-spinners/BarLoader';
|
|||||||
import {GoInfo} from 'react-icons/go';
|
import {GoInfo} from 'react-icons/go';
|
||||||
import {IoIosFlash} from 'react-icons/io';
|
import {IoIosFlash} from 'react-icons/io';
|
||||||
import {useTranslation} from 'react-i18next';
|
import {useTranslation} from 'react-i18next';
|
||||||
import {sendError} from '../../util/analytics';
|
import {sendError, sendExpandEvent} from '../../util/analytics';
|
||||||
|
|
||||||
import {mobile} from '../../util/css';
|
import {mobile} from '../../util/css';
|
||||||
import {ExternalLink} from '../Links';
|
import {ExternalLink} from '../Links';
|
||||||
@ -38,6 +38,7 @@ export const Repeater: React.FC<{
|
|||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
function onClick() {
|
function onClick() {
|
||||||
|
sendExpandEvent();
|
||||||
setRevealAlternatives(true);
|
setRevealAlternatives(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,16 +10,47 @@ export function initGA(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendQueryStatistics(queryLength: number): void {
|
export function track({
|
||||||
|
category,
|
||||||
|
action,
|
||||||
|
label = undefined,
|
||||||
|
value = undefined,
|
||||||
|
}: {
|
||||||
|
category: string;
|
||||||
|
action: string;
|
||||||
|
label?: string;
|
||||||
|
value?: number;
|
||||||
|
}) {
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: 'Search',
|
category,
|
||||||
action: 'New search invoked',
|
action,
|
||||||
value: queryLength,
|
label,
|
||||||
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sendQueryEvent(query: string): void {
|
||||||
|
track({category: 'Search', action: 'search', label: query});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sendExampleQueryEvent(query: string): void {
|
||||||
|
track({category: 'Search', action: 'tryExampleQuery', label: query});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sendExpandEvent(): void {
|
||||||
|
track({category: 'Result', action: 'expand'});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sendAcceptSuggestionEvent(): void {
|
||||||
|
track({category: 'Suggestion', action: 'accept'});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sendShuffleSuggestionEvent(): void {
|
||||||
|
track({category: 'Suggestion', action: 'shuffle'});
|
||||||
|
}
|
||||||
|
|
||||||
export function initSentry(): void {
|
export function initSentry(): void {
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user