Skip to content

Commit

Permalink
fix: log location analytics (#27)
Browse files Browse the repository at this point in the history
* feat: move url log into content script

Signed-off-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* feat: remove analytics init froom background

Signed-off-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* fix: location analytics

Signed-off-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* feat: add comment to location parsing

Signed-off-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
  • Loading branch information
Patrick-Erichsen authored Nov 7, 2021
1 parent 02c1ab5 commit 6da897f
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 48 deletions.
6 changes: 1 addition & 5 deletions src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { rollbar, initAnalytics, logUrlChange } from '../utils';
import { rollbar } from '../utils';
import { ChromeUninstallUrlUpdate, ChromeUrlUpdate } from '../types/Chrome';

initAnalytics();

export const isUninstallMsg = (
msg: unknown | ChromeUninstallUrlUpdate
): msg is ChromeUninstallUrlUpdate => {
Expand All @@ -14,8 +12,6 @@ export const isUninstallMsg = (

chrome.tabs.onUpdated.addListener((tabId, { url }) => {
if (url) {
logUrlChange(url);

const newUrl: ChromeUrlUpdate = { event: 'URL_UPDATE', url };

chrome.tabs.sendMessage(tabId, newUrl);
Expand Down
21 changes: 14 additions & 7 deletions src/content/hooks/useUrlChangeChrome.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect } from 'react';
import { ChromeUrlUpdate } from '../../types/Chrome';
import { tryIdentifyUserFromUrlParam } from '../../utils/analytics';
import {
logUrlChange,
tryIdentifyUserFromUrlParam,
} from '../../utils/analytics';

/**
* Invoke the `onUrlChange` param when Chrome detects that
Expand All @@ -16,20 +19,24 @@ export const useUrlChangeChrome = (
runOnInit = true
): void => {
useEffect(() => {
const initialUrl = window.location.href;

tryIdentifyUserFromUrlParam(initialUrl);
logUrlChange(initialUrl);

if (runOnInit) {
onUrlChange(initialUrl);
}

const onUrlChangeWrapper = (request: ChromeUrlUpdate) => {
if (request.event === 'URL_UPDATE') {
logUrlChange(request.url);
onUrlChange(request.url);
}
};

chrome.runtime.onMessage.addListener(onUrlChangeWrapper);

if (runOnInit) {
onUrlChange(window.location.href);
}

tryIdentifyUserFromUrlParam(window.location.href);

return () => {
chrome.runtime.onMessage.removeListener(onUrlChangeWrapper);
};
Expand Down
23 changes: 12 additions & 11 deletions src/content/utils/__tests__/airbnb.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,49 @@ jest.mock('mixpanel-browser');
describe('airbnb.ts', () => {
describe('getSearchLocation()', () => {
it('returns a `country` key when one location is provided', () => {
const locations = airbnb.getSearchLocation('United States');
const locations = airbnb.getSearchLocation(
'/s/United States/homes'
);
expect(locations.country).toEqual('United States');
});

it('returns a `state` key when two locations are provided', () => {
const locations = airbnb.getSearchLocation('HI, United States');
const locations = airbnb.getSearchLocation(
'/s/HI--United-States/homes'
);
expect(locations.state).toEqual('HI');
});

it('returns a `city` key when three locations are provided', () => {
const locations = airbnb.getSearchLocation(
'Honolulu, HI, United States'
'/s/Honolulu--HI--United-States/homes'
);
expect(locations.city).toEqual('Honolulu');
});

it('returns a `neighborhood` key when four locations are provided', () => {
const locations = airbnb.getSearchLocation(
'Waikīkī, Honolulu, HI, United States'
'/s/Waikīkī--Honolulu--HI--United-States/homes'
);
expect(locations.neighborhood).toEqual('Waikīkī');
});

it('returns a `poi` key when five locations are provided', () => {
const locationStr = 'Oahu, Waikīkī, Honolulu, HI, United States';
const locations = airbnb.getSearchLocation(locationStr);
const locations = airbnb.getSearchLocation(
'/s/Oahu--Waikīkī--Honolulu--HI--United-States/homes'
);

expect(locations.poi).toEqual('Oahu');
});

it('returns a `unknown` key with the full string if more than five locations are provided', () => {
const locationStr =
'Test, Oahu, Waikīkī, Honolulu, HI, United States';
'/s/Test--Oahu--Waikīkī--Honolulu--HI--United-States/homes';

const locations = airbnb.getSearchLocation(locationStr);

expect(locations.unknown).toEqual(locationStr);
});

it('returns an empty object if the param is undefined', () => {
expect(airbnb.getSearchLocation(undefined)).toEqual({});
});
});

describe('getFilterString()', () => {
Expand Down
28 changes: 13 additions & 15 deletions src/content/utils/airbnb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,30 +173,28 @@ export const filterKeyToStringMap: {
};

/**
* Parse our the individual location types from the `query` key
* in `search` portion of a URL.
* Parse our the individual location types from the pathname of
* a search.
*/
export const getSearchLocation = (
query: qs.ParsedQs[string]
): AirbnbLocation => {
if (!query) {
return {};
}

// Assume that the query value is a string
// eslint-disable-next-line no-param-reassign
query = query as string;
export const getSearchLocation = (pathname: string): AirbnbLocation => {
/**
* Index of the split pathname that includes the location.
*
* Example: `/s/United States/homes`
*/
const LOCATION_PATHNAME_INDEX = 2;

const locations = query
.split(', ')
const locations = pathname
.split('/')
[LOCATION_PATHNAME_INDEX].split('--')
.map((location) => location.replace('-', ' '));

if (locations.length > 5) {
rollbar.warning(
`Failed to find expected number of locations in Airbnb location string! Num locations found: ${locations.length}`
);

return { unknown: query };
return { unknown: pathname };
}

const locationKeys: Array<keyof AirbnbLocation> = [
Expand Down
6 changes: 2 additions & 4 deletions src/content/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ export const sortReviewsByDateDesc = (
};

/**
* Parse a URL string using our default configuration
* Parse the search portion of a URL using our default configuration
*/
export const getParsedUrlSearch = (url: string): qs.ParsedQs => {
const { search } = new URL(url);

export const getParsedUrlSearch = (search: string): qs.ParsedQs => {
return qs.parse(search, {
ignoreQueryPrefix: true,
});
Expand Down
17 changes: 11 additions & 6 deletions src/utils/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ export const initAnalytics = (): void => {
};

export const tryIdentifyUserFromUrlParam = (url: string): void => {
const search = getParsedUrlSearch(url);
const { search } = new URL(url);

const urlMixpanelId = search.mixpanel_id;
const parsedSearch = getParsedUrlSearch(search);

const urlMixpanelId = parsedSearch.mixpanel_id;

if (typeof urlMixpanelId !== 'string') {
return;
Expand All @@ -45,11 +47,14 @@ export const tryIdentifyUserFromUrlParam = (url: string): void => {
}
};

export const logUrlChange = (urlStr: string): void => {
const search = getParsedUrlSearch(urlStr);
export const logUrlChange = (url: string): void => {
const { search, pathname } = new URL(url);

const decodedPathname = decodeURIComponent(pathname);
const parsedSearch = getParsedUrlSearch(search);

const locations = getSearchLocation(search.query);
const filters = getMappedSearchFilters(search);
const locations = getSearchLocation(decodedPathname);
const filters = getMappedSearchFilters(parsedSearch);

mixpanel.track(eventNames.AIRBNB_SEARCH_URL, { ...locations, ...filters });
};
Expand Down

0 comments on commit 6da897f

Please # to comment.