Use the canonical url for analytics page views

This commit is contained in:
Kimmo Puputti 2017-10-26 11:41:48 +03:00
parent ceb87c2bb0
commit 5942d11cb6
3 changed files with 97 additions and 4 deletions

View file

@ -8,6 +8,8 @@ import { NamedRedirect } from './components';
import { locationChanged } from './ducks/Routing.duck';
import * as propTypes from './util/propTypes';
import * as log from './util/log';
import { canonicalRouteUrl } from './util/routes';
import routeConfiguration from './routeConfiguration';
const { arrayOf, bool, object, func, shape, string } = PropTypes;
@ -36,9 +38,8 @@ const callLoadData = props => {
};
const handleLocationChanged = (dispatch, location) => {
const { pathname, search, hash } = location;
const canonicalUrl = `${pathname}${search}${hash}`;
dispatch(locationChanged(location, canonicalUrl));
const url = canonicalRouteUrl(routeConfiguration(), location);
dispatch(locationChanged(location, url));
};
class RouteComponentRenderer extends Component {

View file

@ -88,3 +88,32 @@ export const findRouteByRouteName = (nameToFind, routes) => {
}
return route;
};
/**
* Get the canonical URL from the given location
*
* @param {Array<{ route }>} routes - Route configuration as flat array
* @param {Object} location - location object from React Router
*
* @return {String} Canonical URL of the given location
*
*/
export const canonicalRouteUrl = (routes, location) => {
const { pathname, search, hash } = location;
const matches = matchPathname(pathname, routes);
const isListingRoute = matches.length === 1 && matches[0].route.name === 'ListingPage';
if (isListingRoute) {
// Remove the dynamic slug from the listing page canonical URL
const parts = pathname.split('/');
if (parts.length !== 4) {
throw new Error('Expecting ListingPage pathname to have 4 parts');
}
const canonicalListingPathname = `/${parts[1]}/${parts[3]}`;
return `${canonicalListingPathname}${search}${hash}`;
}
return `${pathname}${search}${hash}`;
};

View file

@ -4,7 +4,7 @@ import { RoutesProvider } from '../components';
import routeConfiguration from '../routeConfiguration';
import { renderDeep, renderShallow } from './test-helpers';
import * as propTypes from './propTypes';
import { createResourceLocatorString, findRouteByRouteName } from './routes';
import { createResourceLocatorString, findRouteByRouteName, canonicalRouteUrl } from './routes';
const { arrayOf } = PropTypes;
@ -68,4 +68,67 @@ describe('util/routes.js', () => {
);
});
});
describe('canonicalRouteUrl', () => {
it('handles non-listing route', () => {
const routes = routeConfiguration();
const location = {
pathname: '/',
search: '?some=value',
hash: '#and-some-hash',
};
expect(canonicalRouteUrl(routes, location)).toEqual('/?some=value#and-some-hash');
});
it('handles ListingPage', () => {
const routes = routeConfiguration();
const location = {
pathname: '/l/some-slug-here/00000000-0000-0000-0000-000000000000',
search: '',
hash: '',
};
expect(canonicalRouteUrl(routes, location)).toEqual(
'/l/00000000-0000-0000-0000-000000000000'
);
});
it('handles ListingBasePage', () => {
const routes = routeConfiguration();
const location = {
pathname: '/l',
search: '',
hash: '',
};
expect(canonicalRouteUrl(routes, location)).toEqual('/l');
});
it('handles CheckoutPage', () => {
const routes = routeConfiguration();
const location = {
pathname: '/l/some-slug-here/00000000-0000-0000-0000-000000000000/checkout',
search: '',
hash: '',
};
expect(canonicalRouteUrl(routes, location)).toEqual(
'/l/some-slug-here/00000000-0000-0000-0000-000000000000/checkout'
);
});
it('handles NewListingPage', () => {
const routes = routeConfiguration();
const location = {
pathname: '/l/new',
search: '',
hash: '',
};
expect(canonicalRouteUrl(routes, location)).toEqual('/l/new');
});
it('handles ListingPageCanonical', () => {
const routes = routeConfiguration();
const location = {
pathname: '/l/00000000-0000-0000-0000-000000000000',
search: '',
hash: '',
};
expect(canonicalRouteUrl(routes, location)).toEqual(
'/l/00000000-0000-0000-0000-000000000000'
);
});
});
});