diff --git a/components/WebsiteDetails.js b/components/WebsiteDetails.js
index e3a7e2c2..0fa20284 100644
--- a/components/WebsiteDetails.js
+++ b/components/WebsiteDetails.js
@@ -1,6 +1,5 @@
 import React, { useState } from 'react';
 import { FormattedMessage } from 'react-intl';
-import { useRouter } from 'next/router';
 import classNames from 'classnames';
 import WebsiteChart from 'components/metrics/WebsiteChart';
 import WorldMap from 'components/common/WorldMap';
@@ -19,6 +18,7 @@ import EventsTable from './metrics/EventsTable';
 import EventsChart from './metrics/EventsChart';
 import useFetch from 'hooks/useFetch';
 import Loading from 'components/common/Loading';
+import usePageQuery from '../hooks/usePageQuery';
 
 const views = {
   url: PagesTable,
@@ -31,18 +31,16 @@ const views = {
 };
 
 export default function WebsiteDetails({ websiteId, token }) {
-  const router = useRouter();
   const { data } = useFetch(`/api/website/${websiteId}`, { token });
   const [chartLoaded, setChartLoaded] = useState(false);
   const [countryData, setCountryData] = useState();
   const [eventsData, setEventsData] = useState();
   const {
-    query: { id, view },
-    basePath,
-    asPath,
-  } = router;
-
-  const path = `${basePath}/${asPath.split('/')[1]}/${id.join('/')}`;
+    pathname,
+    resolve,
+    router,
+    query: { view },
+  } = usePageQuery();
 
   const BackButton = () => (
     <Button
@@ -50,11 +48,9 @@ export default function WebsiteDetails({ websiteId, token }) {
       className={styles.backButton}
       icon={<Arrow />}
       size="xsmall"
-      onClick={() => router.push(path)}
+      onClick={() => router.push(pathname)}
     >
-      <div>
-        <FormattedMessage id="button.back" defaultMessage="Back" />
-      </div>
+      <FormattedMessage id="button.back" defaultMessage="Back" />
     </Button>
   );
 
@@ -64,31 +60,31 @@ export default function WebsiteDetails({ websiteId, token }) {
     },
     {
       label: <FormattedMessage id="metrics.pages" defaultMessage="Pages" />,
-      value: `${path}?view=url`,
+      value: resolve({ view: 'url' }),
     },
     {
       label: <FormattedMessage id="metrics.referrers" defaultMessage="Referrers" />,
-      value: `${path}?view=referrer`,
+      value: resolve({ view: 'referrer' }),
     },
     {
       label: <FormattedMessage id="metrics.browsers" defaultMessage="Browsers" />,
-      value: `${path}?view=browser`,
+      value: resolve({ view: 'browser' }),
     },
     {
       label: <FormattedMessage id="metrics.operating-systems" defaultMessage="Operating system" />,
-      value: `${path}?view=os`,
+      value: resolve({ view: 'os' }),
     },
     {
       label: <FormattedMessage id="metrics.devices" defaultMessage="Devices" />,
-      value: `${path}?view=device`,
+      value: resolve({ view: 'device' }),
     },
     {
       label: <FormattedMessage id="metrics.countries" defaultMessage="Countries" />,
-      value: `${path}?view=country`,
+      value: resolve({ view: 'country' }),
     },
     {
       label: <FormattedMessage id="metrics.events" defaultMessage="Events" />,
-      value: `${path}?view=event`,
+      value: resolve({ view: 'event' }),
     },
   ];
 
@@ -109,7 +105,7 @@ export default function WebsiteDetails({ websiteId, token }) {
   }
 
   function handleExpand(value) {
-    router.push(`${path}?view=${value}`);
+    router.push(resolve({ view: value }));
   }
 
   if (!data) {
@@ -179,7 +175,7 @@ export default function WebsiteDetails({ websiteId, token }) {
           contentClassName={styles.content}
           menu={menuOptions}
         >
-          <DetailsComponent {...tableProps} limit={false} />
+          <DetailsComponent {...tableProps} limit={false} showFilters={true} />
         </MenuLayout>
       )}
     </Page>
diff --git a/components/WebsiteList.js b/components/WebsiteList.js
index b1819748..0df24877 100644
--- a/components/WebsiteList.js
+++ b/components/WebsiteList.js
@@ -34,9 +34,7 @@ export default function WebsiteList({ userId }) {
           }
         >
           <Button icon={<Arrow />} size="medium" onClick={() => router.push('/settings')}>
-            <div>
-              <FormattedMessage id="message.go-to-settings" defaultMessage="Go to settings" />
-            </div>
+            <FormattedMessage id="message.go-to-settings" defaultMessage="Go to settings" />
           </Button>
         </EmptyPlaceholder>
       )}
diff --git a/components/common/Button.js b/components/common/Button.js
index b973b36e..f769ba6f 100644
--- a/components/common/Button.js
+++ b/components/common/Button.js
@@ -13,7 +13,8 @@ export default function Button({
   className,
   tooltip,
   tooltipId,
-  disabled = false,
+  disabled,
+  iconRight,
   onClick = () => {},
   ...props
 }) {
@@ -30,14 +31,14 @@ export default function Button({
         [styles.action]: variant === 'action',
         [styles.danger]: variant === 'danger',
         [styles.light]: variant === 'light',
-        [styles.disabled]: disabled,
+        [styles.iconRight]: iconRight,
       })}
       disabled={disabled}
       onClick={!disabled ? onClick : null}
       {...props}
     >
-      {icon && <Icon icon={icon} size={size} />}
-      {children}
+      {icon && <Icon className={styles.icon} icon={icon} size={size} />}
+      {children && <div>{children}</div>}
       {tooltip && <ReactTooltip id={tooltipId}>{tooltip}</ReactTooltip>}
     </button>
   );
diff --git a/components/common/Button.module.css b/components/common/Button.module.css
index 324bbb22..51341fee 100644
--- a/components/common/Button.module.css
+++ b/components/common/Button.module.css
@@ -38,7 +38,8 @@
   font-size: var(--font-size-xsmall);
 }
 
-.action {
+.action,
+.action:active {
   color: var(--gray50);
   background: var(--gray900);
 }
@@ -64,6 +65,19 @@
   background: inherit;
 }
 
+.button .icon + div {
+  margin-left: 10px;
+}
+
+.button.iconRight .icon {
+  order: 1;
+  margin-left: 10px;
+}
+
+.button.iconRight .icon + div {
+  margin: 0;
+}
+
 .button:disabled {
   cursor: default;
   color: var(--gray500);
diff --git a/components/common/Icon.module.css b/components/common/Icon.module.css
index 47d0ab0d..5b431668 100644
--- a/components/common/Icon.module.css
+++ b/components/common/Icon.module.css
@@ -5,10 +5,6 @@
   vertical-align: middle;
 }
 
-.icon + * {
-  margin-left: 10px;
-}
-
 .icon svg {
   fill: currentColor;
 }
diff --git a/components/metrics/EventsChart.js b/components/metrics/EventsChart.js
index afc3e952..113c6f56 100644
--- a/components/metrics/EventsChart.js
+++ b/components/metrics/EventsChart.js
@@ -6,11 +6,13 @@ import useFetch from 'hooks/useFetch';
 import useDateRange from 'hooks/useDateRange';
 import useTimezone from 'hooks/useTimezone';
 import { EVENT_COLORS } from 'lib/constants';
+import usePageQuery from '../../hooks/usePageQuery';
 
 export default function EventsChart({ websiteId, token }) {
   const [dateRange] = useDateRange(websiteId);
   const { startDate, endDate, unit, modified } = dateRange;
   const [timezone] = useTimezone();
+  const { query } = usePageQuery();
 
   const { data } = useFetch(
     `/api/website/${websiteId}/events`,
@@ -19,6 +21,7 @@ export default function EventsChart({ websiteId, token }) {
       end_at: +endDate,
       unit,
       tz: timezone,
+      url: query.url,
       token,
     },
     { update: [modified] },
diff --git a/components/metrics/MetricsBar.js b/components/metrics/MetricsBar.js
index cad4c00e..f5d888d4 100644
--- a/components/metrics/MetricsBar.js
+++ b/components/metrics/MetricsBar.js
@@ -5,24 +5,30 @@ import Loading from 'components/common/Loading';
 import useFetch from 'hooks/useFetch';
 import useDateRange from 'hooks/useDateRange';
 import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
+import usePageQuery from 'hooks/usePageQuery';
 import MetricCard from './MetricCard';
 import styles from './MetricsBar.module.css';
 
 export default function MetricsBar({ websiteId, token, className }) {
   const [dateRange] = useDateRange(websiteId);
   const { startDate, endDate, modified } = dateRange;
+  const [format, setFormat] = useState(true);
+  const {
+    query: { url },
+  } = usePageQuery();
+
   const { data } = useFetch(
     `/api/website/${websiteId}/metrics`,
     {
       start_at: +startDate,
       end_at: +endDate,
+      url,
       token,
     },
     {
       update: [modified],
     },
   );
-  const [format, setFormat] = useState(true);
 
   const formatFunc = format ? formatLongNumber : formatNumber;
 
diff --git a/components/metrics/MetricsTable.js b/components/metrics/MetricsTable.js
index 75fd579c..16b5db90 100644
--- a/components/metrics/MetricsTable.js
+++ b/components/metrics/MetricsTable.js
@@ -12,6 +12,7 @@ import { percentFilter } from 'lib/filters';
 import { formatNumber, formatLongNumber } from 'lib/format';
 import useDateRange from 'hooks/useDateRange';
 import styles from './MetricsTable.module.css';
+import usePageQuery from '../../hooks/usePageQuery';
 
 export default function MetricsTable({
   websiteId,
@@ -30,6 +31,10 @@ export default function MetricsTable({
 }) {
   const [dateRange] = useDateRange(websiteId);
   const { startDate, endDate, modified } = dateRange;
+  const {
+    query: { url },
+  } = usePageQuery();
+
   const { data } = useFetch(
     `/api/website/${websiteId}/rankings`,
     {
@@ -37,6 +42,7 @@ export default function MetricsTable({
       start_at: +startDate,
       end_at: +endDate,
       domain: websiteDomain,
+      url,
       token,
     },
     { onDataLoad, delay: 300, update: [modified] },
@@ -101,9 +107,7 @@ export default function MetricsTable({
           <div className={styles.footer}>
             {limit && (
               <Button icon={<Arrow />} size="xsmall" onClick={() => onExpand(type)}>
-                <div>
-                  <FormattedMessage id="button.more" defaultMessage="More" />
-                </div>
+                <FormattedMessage id="button.more" defaultMessage="More" />
               </Button>
             )}
           </div>
diff --git a/components/metrics/PagesTable.js b/components/metrics/PagesTable.js
index ba04f871..46a17fdb 100644
--- a/components/metrics/PagesTable.js
+++ b/components/metrics/PagesTable.js
@@ -1,13 +1,23 @@
 import React, { useState } from 'react';
 import { FormattedMessage } from 'react-intl';
+import Link from 'next/link';
 import ButtonGroup from 'components/common/ButtonGroup';
+import ButtonLayout from 'components/layout/ButtonLayout';
 import { urlFilter } from 'lib/filters';
 import { FILTER_COMBINED, FILTER_RAW } from 'lib/constants';
+import usePageQuery from 'hooks/usePageQuery';
 import MetricsTable from './MetricsTable';
-import ButtonLayout from '../layout/ButtonLayout';
 
-export default function PagesTable({ websiteId, token, websiteDomain, limit, onExpand }) {
+export default function PagesTable({
+  websiteId,
+  token,
+  websiteDomain,
+  limit,
+  showFilters,
+  onExpand,
+}) {
   const [filter, setFilter] = useState(FILTER_COMBINED);
+  const { resolve } = usePageQuery();
 
   const buttons = [
     {
@@ -17,9 +27,17 @@ export default function PagesTable({ websiteId, token, websiteDomain, limit, onE
     { label: <FormattedMessage id="metrics.filter.raw" defaultMessage="Raw" />, value: FILTER_RAW },
   ];
 
+  const renderLink = ({ x }) => {
+    return (
+      <Link href={resolve({ url: x })} replace={true}>
+        <a>{decodeURI(x)}</a>
+      </Link>
+    );
+  };
+
   return (
     <>
-      {!limit && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
+      {showFilters && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
       <MetricsTable
         title={<FormattedMessage id="metrics.pages" defaultMessage="Pages" />}
         type="url"
@@ -29,7 +47,7 @@ export default function PagesTable({ websiteId, token, websiteDomain, limit, onE
         limit={limit}
         dataFilter={urlFilter}
         filterOptions={{ domain: websiteDomain, raw: filter === FILTER_RAW }}
-        renderLabel={({ x }) => decodeURI(x)}
+        renderLabel={renderLink}
         onExpand={onExpand}
       />
     </>
diff --git a/components/metrics/ReferrersTable.js b/components/metrics/ReferrersTable.js
index 93552cc5..3b8d607d 100644
--- a/components/metrics/ReferrersTable.js
+++ b/components/metrics/ReferrersTable.js
@@ -11,6 +11,7 @@ export default function ReferrersTable({
   websiteDomain,
   token,
   limit,
+  showFilters,
   onExpand = () => {},
 }) {
   const [filter, setFilter] = useState(FILTER_COMBINED);
@@ -39,7 +40,7 @@ export default function ReferrersTable({
 
   return (
     <>
-      {!limit && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
+      {showFilters && <FilterButtons buttons={buttons} selected={filter} onClick={setFilter} />}
       <MetricsTable
         title={<FormattedMessage id="metrics.referrers" defaultMessage="Referrers" />}
         type="referrer"
diff --git a/components/metrics/WebsiteChart.js b/components/metrics/WebsiteChart.js
index ecbd0798..ae0907fb 100644
--- a/components/metrics/WebsiteChart.js
+++ b/components/metrics/WebsiteChart.js
@@ -5,10 +5,13 @@ import MetricsBar from './MetricsBar';
 import WebsiteHeader from './WebsiteHeader';
 import DateFilter from 'components/common/DateFilter';
 import StickyHeader from 'components/helpers/StickyHeader';
+import Button from 'components/common/Button';
 import useFetch from 'hooks/useFetch';
 import useDateRange from 'hooks/useDateRange';
 import useTimezone from 'hooks/useTimezone';
+import usePageQuery from 'hooks/usePageQuery';
 import { getDateArray, getDateLength } from 'lib/date';
+import Times from 'assets/times.svg';
 import styles from './WebsiteChart.module.css';
 
 export default function WebsiteChart({
@@ -22,6 +25,11 @@ export default function WebsiteChart({
   const [dateRange, setDateRange] = useDateRange(websiteId);
   const { startDate, endDate, unit, value, modified } = dateRange;
   const [timezone] = useTimezone();
+  const {
+    router,
+    resolve,
+    query: { url },
+  } = usePageQuery();
 
   const { data, loading } = useFetch(
     `/api/website/${websiteId}/pageviews`,
@@ -30,6 +38,7 @@ export default function WebsiteChart({
       end_at: +endDate,
       unit,
       tz: timezone,
+      url,
       token,
     },
     { onDataLoad, update: [modified] },
@@ -45,6 +54,10 @@ export default function WebsiteChart({
     return [[], []];
   }, [data]);
 
+  function handleCloseFilter() {
+    router.push(resolve({ url: undefined }));
+  }
+
   return (
     <>
       <WebsiteHeader websiteId={websiteId} token={token} title={title} showLink={showLink} />
@@ -54,6 +67,7 @@ export default function WebsiteChart({
           stickyClassName={styles.sticky}
           enabled={stickyHeader}
         >
+          {url && <PageFilter url={url} onClick={handleCloseFilter} />}
           <div className="col-12 col-lg-9">
             <MetricsBar websiteId={websiteId} token={token} />
           </div>
@@ -81,3 +95,13 @@ export default function WebsiteChart({
     </>
   );
 }
+
+const PageFilter = ({ url, onClick }) => {
+  return (
+    <div className={classNames(styles.url, 'col-12')}>
+      <Button icon={<Times />} onClick={onClick} variant="action" iconRight={true}>
+        {url}
+      </Button>
+    </div>
+  );
+};
diff --git a/components/metrics/WebsiteChart.module.css b/components/metrics/WebsiteChart.module.css
index ea0fcaee..29f94670 100644
--- a/components/metrics/WebsiteChart.module.css
+++ b/components/metrics/WebsiteChart.module.css
@@ -36,6 +36,11 @@
   align-items: center;
 }
 
+.url {
+  text-align: center;
+  margin-bottom: 10px;
+}
+
 @media only screen and (max-width: 992px) {
   .filter {
     display: block;
diff --git a/components/settings/AccountSettings.js b/components/settings/AccountSettings.js
index bf02f4b3..aa206fa9 100644
--- a/components/settings/AccountSettings.js
+++ b/components/settings/AccountSettings.js
@@ -42,14 +42,10 @@ export default function AccountSettings() {
     row.username !== 'admin' ? (
       <ButtonLayout align="right">
         <Button icon={<Pen />} size="small" onClick={() => setEditAccount(row)}>
-          <div>
-            <FormattedMessage id="button.edit" defaultMessage="Edit" />
-          </div>
+          <FormattedMessage id="button.edit" defaultMessage="Edit" />
         </Button>
         <Button icon={<Trash />} size="small" onClick={() => setDeleteAccount(row)}>
-          <div>
-            <FormattedMessage id="button.delete" defaultMessage="Delete" />
-          </div>
+          <FormattedMessage id="button.delete" defaultMessage="Delete" />
         </Button>
       </ButtonLayout>
     ) : null;
@@ -102,9 +98,7 @@ export default function AccountSettings() {
           <FormattedMessage id="label.accounts" defaultMessage="Accounts" />
         </div>
         <Button icon={<Plus />} size="small" onClick={() => setAddAccount(true)}>
-          <div>
-            <FormattedMessage id="button.add-account" defaultMessage="Add account" />
-          </div>
+          <FormattedMessage id="button.add-account" defaultMessage="Add account" />
         </Button>
       </PageHeader>
       <Table columns={columns} rows={data} />
diff --git a/components/settings/ProfileSettings.js b/components/settings/ProfileSettings.js
index f28226c5..e23c73ed 100644
--- a/components/settings/ProfileSettings.js
+++ b/components/settings/ProfileSettings.js
@@ -29,9 +29,7 @@ export default function ProfileSettings() {
           <FormattedMessage id="label.profile" defaultMessage="Profile" />
         </div>
         <Button icon={<Dots />} size="small" onClick={() => setChangePassword(true)}>
-          <div>
-            <FormattedMessage id="button.change-password" defaultMessage="Change password" />
-          </div>
+          <FormattedMessage id="button.change-password" defaultMessage="Change password" />
         </Button>
       </PageHeader>
       <dl className={styles.list}>
diff --git a/components/settings/ThemeButton.js b/components/settings/ThemeButton.js
index a31440b7..6f32e23b 100644
--- a/components/settings/ThemeButton.js
+++ b/components/settings/ThemeButton.js
@@ -1,6 +1,5 @@
 import React from 'react';
 import { useTransition, animated } from 'react-spring';
-import Button from 'components/common/Button';
 import useTheme from 'hooks/useTheme';
 import Sun from 'assets/sun.svg';
 import Moon from 'assets/moon.svg';
@@ -27,7 +26,7 @@ export default function ThemeButton() {
   }
 
   return (
-    <Button className={styles.button} variant="light" onClick={handleClick}>
+    <div className={styles.button} onClick={handleClick}>
       {transitions.map(({ item, key, props }) =>
         item === 'light' ? (
           <animated.div key={key} style={props}>
@@ -39,6 +38,6 @@ export default function ThemeButton() {
           </animated.div>
         ),
       )}
-    </Button>
+    </div>
   );
 }
diff --git a/components/settings/ThemeButton.module.css b/components/settings/ThemeButton.module.css
index 84fa7139..bc941834 100644
--- a/components/settings/ThemeButton.module.css
+++ b/components/settings/ThemeButton.module.css
@@ -1,5 +1,10 @@
 .button {
   width: 50px;
+  height: 50px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
 }
 
 .button svg {
diff --git a/components/settings/WebsiteSettings.js b/components/settings/WebsiteSettings.js
index 23f6162b..17fc5952 100644
--- a/components/settings/WebsiteSettings.js
+++ b/components/settings/WebsiteSettings.js
@@ -52,14 +52,10 @@ export default function WebsiteSettings() {
         onClick={() => setShowCode(row)}
       />
       <Button icon={<Pen />} size="small" onClick={() => setEditWebsite(row)}>
-        <div>
-          <FormattedMessage id="button.edit" defaultMessage="Edit" />
-        </div>
+        <FormattedMessage id="button.edit" defaultMessage="Edit" />
       </Button>
       <Button icon={<Trash />} size="small" onClick={() => setDeleteWebsite(row)}>
-        <div>
-          <FormattedMessage id="button.delete" defaultMessage="Delete" />
-        </div>
+        <FormattedMessage id="button.delete" defaultMessage="Delete" />
       </Button>
     </ButtonLayout>
   );
@@ -117,9 +113,7 @@ export default function WebsiteSettings() {
       }
     >
       <Button icon={<Plus />} size="medium" onClick={() => setAddWebsite(true)}>
-        <div>
-          <FormattedMessage id="button.add-website" defaultMessage="Add website" />
-        </div>
+        <FormattedMessage id="button.add-website" defaultMessage="Add website" />
       </Button>
     </EmptyPlaceholder>
   );
@@ -131,9 +125,7 @@ export default function WebsiteSettings() {
           <FormattedMessage id="label.websites" defaultMessage="Websites" />
         </div>
         <Button icon={<Plus />} size="small" onClick={() => setAddWebsite(true)}>
-          <div>
-            <FormattedMessage id="button.add-website" defaultMessage="Add website" />
-          </div>
+          <FormattedMessage id="button.add-website" defaultMessage="Add website" />
         </Button>
       </PageHeader>
       <Table columns={columns} rows={data} empty={empty} />
diff --git a/hooks/usePageQuery.js b/hooks/usePageQuery.js
new file mode 100644
index 00000000..ced19702
--- /dev/null
+++ b/hooks/usePageQuery.js
@@ -0,0 +1,32 @@
+import { useMemo } from 'react';
+import { useRouter } from 'next/router';
+import { getQueryString } from '../lib/url';
+
+export default function usePageQuery() {
+  const router = useRouter();
+  const { pathname, search } = location;
+
+  const query = useMemo(() => {
+    if (!search) {
+      return {};
+    }
+
+    const params = search.substring(1).split('&');
+
+    return params.reduce((obj, item) => {
+      const [key, value] = item.split('=');
+
+      obj[key] = decodeURIComponent(value);
+
+      return obj;
+    }, {});
+  }, [search]);
+
+  function resolve(params) {
+    const search = getQueryString({ ...query, ...params });
+
+    return `${pathname}${search}`;
+  }
+
+  return { pathname, query, resolve, router };
+}
diff --git a/lib/filters.js b/lib/filters.js
index acdab7a3..dcbb9907 100644
--- a/lib/filters.js
+++ b/lib/filters.js
@@ -13,7 +13,7 @@ export const urlFilter = (data, { raw }) => {
 
   const cleanUrl = url => {
     try {
-      const { pathname, search } = new URL(url);
+      const { pathname, search } = new URL(url, location.origin);
 
       if (search.startsWith('?/')) {
         return `${pathname}${search}`;
@@ -30,7 +30,7 @@ export const urlFilter = (data, { raw }) => {
       return obj;
     }
 
-    const url = cleanUrl(`http://x${x}`);
+    const url = cleanUrl(x);
 
     if (url) {
       if (!obj[url]) {
diff --git a/lib/queries.js b/lib/queries.js
index c16f1ac0..af2b7f5b 100644
--- a/lib/queries.js
+++ b/lib/queries.js
@@ -21,7 +21,7 @@ export async function runQuery(query) {
   });
 }
 
-export async function rawQuery(query, ...params) {
+export async function rawQuery(query, params) {
   const db = getDatabase();
 
   if (db !== POSTGRESQL && db !== MYSQL) {
@@ -285,7 +285,15 @@ export async function createAccount(data) {
   );
 }
 
-export function getMetrics(website_id, start_at, end_at) {
+export function getMetrics(website_id, start_at, end_at, url) {
+  const params = [website_id, start_at, end_at];
+  let urlFilter = '';
+
+  if (url) {
+    urlFilter = `and url=$${params.length + 1}`;
+    params.push(decodeURIComponent(url));
+  }
+
   return rawQuery(
     `
       select sum(t.c) as "pageviews",
@@ -300,12 +308,11 @@ export function getMetrics(website_id, start_at, end_at) {
          from pageview
          where website_id=$1
          and created_at between $2 and $3
+         ${urlFilter}
          group by 1, 2
      ) t
     `,
-    website_id,
-    start_at,
-    end_at,
+    params,
   );
 }
 
@@ -316,7 +323,16 @@ export function getPageviews(
   timezone = 'utc',
   unit = 'day',
   count = '*',
+  url,
 ) {
+  const params = [website_id, start_at, end_at];
+  let urlFilter = '';
+
+  if (url) {
+    urlFilter = `and url=$${params.length + 1}`;
+    params.push(decodeURIComponent(url));
+  }
+
   return rawQuery(
     `
     select ${getDateQuery('created_at', unit, timezone)} t,
@@ -324,16 +340,23 @@ export function getPageviews(
     from pageview
     where website_id=$1
     and created_at between $2 and $3
+    ${urlFilter}
     group by 1
     order by 1
     `,
-    website_id,
-    start_at,
-    end_at,
+    params,
   );
 }
 
-export function getSessionMetrics(website_id, start_at, end_at, field) {
+export function getSessionMetrics(website_id, start_at, end_at, field, url) {
+  const params = [website_id, start_at, end_at];
+  let urlFilter = '';
+
+  if (url) {
+    urlFilter = `and url=$${params.length + 1}`;
+    params.push(decodeURIComponent(url));
+  }
+
   return rawQuery(
     `
     select ${field} x, count(*) y
@@ -343,18 +366,29 @@ export function getSessionMetrics(website_id, start_at, end_at, field) {
       from pageview
       where website_id=$1
       and created_at between $2 and $3
+      ${urlFilter}
     )
     group by 1
     order by 2 desc
     `,
-    website_id,
-    start_at,
-    end_at,
+    params,
   );
 }
 
-export function getPageviewMetrics(website_id, start_at, end_at, field, table, domain) {
-  const filter = domain ? `and ${field} not like '%${domain}%'` : '';
+export function getPageviewMetrics(website_id, start_at, end_at, field, table, domain, url) {
+  const params = [website_id, start_at, end_at];
+  let domainFilter = '';
+  let urlFilter = '';
+
+  if (domain) {
+    domainFilter = `and referrer not like $${params.length + 1}`;
+    params.push(`%${domain}%`);
+  }
+
+  if (url) {
+    urlFilter = `and url=$${params.length + 1}`;
+    params.push(decodeURIComponent(url));
+  }
 
   return rawQuery(
     `
@@ -362,18 +396,18 @@ export function getPageviewMetrics(website_id, start_at, end_at, field, table, d
     from ${table}
     where website_id=$1
     and created_at between $2 and $3
-    ${filter}
+    ${domainFilter}
+    ${urlFilter}
     group by 1
     order by 2 desc
     `,
-    website_id,
-    start_at,
-    end_at,
+    params,
   );
 }
 
 export function getActiveVisitors(website_id) {
   const date = subMinutes(new Date(), 5);
+  const params = [website_id, date];
 
   return rawQuery(
     `
@@ -382,12 +416,19 @@ export function getActiveVisitors(website_id) {
     where website_id=$1
     and created_at >= $2
     `,
-    website_id,
-    date,
+    params,
   );
 }
 
-export function getEvents(website_id, start_at, end_at, timezone = 'utc', unit = 'day') {
+export function getEvents(website_id, start_at, end_at, timezone = 'utc', unit = 'day', url) {
+  const params = [website_id, start_at, end_at];
+  let urlFilter = '';
+
+  if (url) {
+    urlFilter = `and url=$${params.length + 1}`;
+    params.push(decodeURIComponent(url));
+  }
+
   return rawQuery(
     `
     select
@@ -397,11 +438,10 @@ export function getEvents(website_id, start_at, end_at, timezone = 'utc', unit =
     from event
     where website_id=$1
     and created_at between $2 and $3
+    ${urlFilter}
     group by 1, 2
     order by 2
     `,
-    website_id,
-    start_at,
-    end_at,
+    params,
   );
 }
diff --git a/lib/url.js b/lib/url.js
index d90c390e..49acedf7 100644
--- a/lib/url.js
+++ b/lib/url.js
@@ -13,3 +13,18 @@ export function getDomainName(str) {
     return str;
   }
 }
+
+export function getQueryString(params) {
+  const map = Object.keys(params).reduce((arr, key) => {
+    if (params[key] !== undefined) {
+      return arr.concat(`${key}=${encodeURIComponent(params[key])}`);
+    }
+    return arr;
+  }, []);
+
+  if (map.length) {
+    return `?${map.join('&')}`;
+  }
+
+  return '';
+}
diff --git a/lib/web.js b/lib/web.js
index 82c1e75b..a20a09c8 100644
--- a/lib/web.js
+++ b/lib/web.js
@@ -1,3 +1,5 @@
+import { getQueryString } from './url';
+
 export const apiRequest = (method, url, body) =>
   fetch(url, {
     method,
@@ -20,19 +22,9 @@ export const apiRequest = (method, url, body) =>
     return null;
   });
 
-const parseQuery = (url, params = {}) => {
-  const query = Object.keys(params).reduce((values, key) => {
-    if (params[key] !== undefined) {
-      return values.concat(`${key}=${encodeURIComponent(params[key])}`);
-    }
-    return values;
-  }, []);
-  return query.length ? `${url}?${query.join('&')}` : url;
-};
+export const get = (url, params) => apiRequest('get', `${url}${getQueryString(params)}`);
 
-export const get = (url, params) => apiRequest('get', parseQuery(url, params));
-
-export const del = (url, params) => apiRequest('delete', parseQuery(url, params));
+export const del = (url, params) => apiRequest('delete', `${url}${getQueryString(params)}`);
 
 export const post = (url, params) => apiRequest('post', url, JSON.stringify(params));
 
diff --git a/package.json b/package.json
index 92a55bee..f0eab672 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "umami",
-  "version": "0.52.0",
+  "version": "0.53.0",
   "description": "A simple, fast, website analytics alternative to Google Analytics. ",
   "author": "Mike Cao <mike@mikecao.com>",
   "license": "MIT",
diff --git a/pages/api/website/[id]/events.js b/pages/api/website/[id]/events.js
index 4b9a656d..da610f17 100644
--- a/pages/api/website/[id]/events.js
+++ b/pages/api/website/[id]/events.js
@@ -11,7 +11,7 @@ export default async (req, res) => {
       return unauthorized(res);
     }
 
-    const { id, start_at, end_at, unit, tz } = req.query;
+    const { id, start_at, end_at, unit, tz, url } = req.query;
 
     if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
       return badRequest(res);
@@ -21,7 +21,7 @@ export default async (req, res) => {
     const startDate = new Date(+start_at);
     const endDate = new Date(+end_at);
 
-    const events = await getEvents(websiteId, startDate, endDate, tz, unit);
+    const events = await getEvents(websiteId, startDate, endDate, tz, unit, url);
 
     return ok(res, events);
   }
diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js
index bb5c977b..f7178bf4 100644
--- a/pages/api/website/[id]/metrics.js
+++ b/pages/api/website/[id]/metrics.js
@@ -8,13 +8,13 @@ export default async (req, res) => {
       return unauthorized(res);
     }
 
-    const { id, start_at, end_at } = req.query;
+    const { id, start_at, end_at, url } = req.query;
 
     const websiteId = +id;
     const startDate = new Date(+start_at);
     const endDate = new Date(+end_at);
 
-    const metrics = await getMetrics(websiteId, startDate, endDate);
+    const metrics = await getMetrics(websiteId, startDate, endDate, url);
 
     const stats = Object.keys(metrics[0]).reduce((obj, key) => {
       obj[key] = Number(metrics[0][key]) || 0;
diff --git a/pages/api/website/[id]/pageviews.js b/pages/api/website/[id]/pageviews.js
index 016c6646..2191a4c4 100644
--- a/pages/api/website/[id]/pageviews.js
+++ b/pages/api/website/[id]/pageviews.js
@@ -11,7 +11,7 @@ export default async (req, res) => {
       return unauthorized(res);
     }
 
-    const { id, start_at, end_at, unit, tz } = req.query;
+    const { id, start_at, end_at, unit, tz, url } = req.query;
 
     const websiteId = +id;
     const startDate = new Date(+start_at);
@@ -22,8 +22,8 @@ export default async (req, res) => {
     }
 
     const [pageviews, uniques] = await Promise.all([
-      getPageviews(websiteId, startDate, endDate, tz, unit, '*'),
-      getPageviews(websiteId, startDate, endDate, tz, unit, 'distinct session_id'),
+      getPageviews(websiteId, startDate, endDate, tz, unit, '*', url),
+      getPageviews(websiteId, startDate, endDate, tz, unit, 'distinct session_id', url),
     ]);
 
     return ok(res, { pageviews, uniques });
diff --git a/pages/api/website/[id]/rankings.js b/pages/api/website/[id]/rankings.js
index 36669c4e..9db8975e 100644
--- a/pages/api/website/[id]/rankings.js
+++ b/pages/api/website/[id]/rankings.js
@@ -31,7 +31,7 @@ export default async (req, res) => {
       return unauthorized(res);
     }
 
-    const { id, type, start_at, end_at, domain } = req.query;
+    const { id, type, start_at, end_at, domain, url } = req.query;
 
     if (domain && !DOMAIN_REGEX.test(domain)) {
       return badRequest(res);
@@ -42,7 +42,7 @@ export default async (req, res) => {
     const endDate = new Date(+end_at);
 
     if (sessionColumns.includes(type)) {
-      const data = await getSessionMetrics(websiteId, startDate, endDate, type);
+      const data = await getSessionMetrics(websiteId, startDate, endDate, type, url);
 
       return ok(res, data);
     }
@@ -55,6 +55,7 @@ export default async (req, res) => {
         getColumn(type),
         getTable(type),
         domain,
+        url,
       );
 
       return ok(res, data);