diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart.vue b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ad0e0eb51ef0884b5776c8dd34f368f89e1924ab
--- /dev/null
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlSkeletonLoader } from '@gitlab/ui';
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
+
+import { s__ } from '~/locale';
+
+import { monthlyTotalsValidator } from '../utils';
+
+export default {
+  name: 'ProductAnalyticsGroupMonthlyUsageChart',
+  components: {
+    GlAreaChart,
+    GlSkeletonLoader,
+  },
+  props: {
+    isLoading: {
+      type: Boolean,
+      required: true,
+    },
+    monthlyTotals: {
+      type: Array,
+      required: false,
+      default: null,
+      validator: monthlyTotalsValidator,
+    },
+  },
+  computed: {
+    chartData() {
+      return [
+        {
+          name: s__('ProductAnalytics|Analytics events by month'),
+          data: this.monthlyTotals,
+        },
+      ];
+    },
+  },
+  CHART_OPTIONS: {
+    yAxis: {
+      name: s__('ProductAnalytics|Events'),
+    },
+    xAxis: {
+      name: s__('ProductAnalytics|Month'),
+      type: 'category',
+    },
+  },
+};
+</script>
+<template>
+  <section>
+    <h2 class="gl-font-lg">{{ s__('ProductAnalytics|Usage by month') }}</h2>
+
+    <gl-skeleton-loader v-if="isLoading" :lines="3" />
+    <template v-else>
+      <gl-area-chart :data="chartData" :option="$options.CHART_OPTIONS" />
+    </template>
+  </section>
+</template>
diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_group_usage.vue b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage.vue
similarity index 67%
rename from ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_group_usage.vue
rename to ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage.vue
index 6de9c86a3096f0eedf0477b003c0e6e3bcef2681..6e36161a9440769d82a3effae9d362f3029b9aca 100644
--- a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_group_usage.vue
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage.vue
@@ -1,25 +1,25 @@
 <script>
-import { GlAlert, GlLink, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
 
 import * as Sentry from '~/sentry/sentry_browser_wrapper';
 import { nMonthsBefore } from '~/lib/utils/datetime/date_calculation_utility';
-import { s__ } from '~/locale';
 import { helpPagePath } from '~/helpers/help_page_helper';
 import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 
-import { projectHasProductAnalyticsEnabled } from '../utils';
-import getGroupProductAnalyticsUsage from '../graphql/queries/get_group_product_analytics_usage.query.graphql';
-import { getCurrentMonth, mapMonthlyTotals } from './utils';
+import { projectHasProductAnalyticsEnabled } from '../../utils';
+import getGroupProductAnalyticsUsage from '../../graphql/queries/get_group_product_analytics_usage.query.graphql';
+import { findCurrentMonthEventsUsed, getCurrentMonth, mapMonthlyTotals } from '../utils';
+import ProductAnalyticsGroupUsageOverview from './product_analytics_group_usage_overview.vue';
+import ProductAnalyticsGroupMonthlyUsageChart from './product_analytics_group_monthly_usage_chart.vue';
 
 export default {
   name: 'ProductAnalyticsGroupUsage',
   components: {
     GlAlert,
-    GlAreaChart,
     GlLink,
-    GlSkeletonLoader,
     GlSprintf,
+    ProductAnalyticsGroupMonthlyUsageChart,
+    ProductAnalyticsGroupUsageOverview,
   },
   mixins: [glFeatureFlagsMixin()],
   inject: {
@@ -30,24 +30,23 @@ export default {
   data() {
     return {
       error: null,
-      projectsUsageData: null,
+      monthlyTotals: null,
+      storedEventsLimit: null,
     };
   },
   computed: {
     isLoading() {
-      return this.$apollo.queries.projectsUsageData.loading;
+      return this.$apollo.queries.monthlyTotals.loading;
     },
-    chartData() {
-      return [
-        {
-          name: s__('ProductAnalytics|Analytics events by month'),
-          data: this.projectsUsageData,
-        },
-      ];
+    showUsageOverview() {
+      return this.glFeatures.productAnalyticsBilling;
+    },
+    eventsUsed() {
+      return findCurrentMonthEventsUsed(this.monthlyTotals);
     },
   },
   apollo: {
-    projectsUsageData: {
+    monthlyTotals: {
       query: getGroupProductAnalyticsUsage,
       variables() {
         return {
@@ -58,6 +57,8 @@ export default {
       update(data) {
         const projects = data.group.projects.nodes.filter(projectHasProductAnalyticsEnabled);
 
+        this.storedEventsLimit = data.group.productAnalyticsStoredEventsLimit;
+
         if (projects.length === 0) {
           this.$emit('no-projects');
           return [];
@@ -90,15 +91,6 @@ export default {
       });
     },
   },
-  CHART_OPTIONS: {
-    yAxis: {
-      name: s__('ProductAnalytics|Events'),
-    },
-    xAxis: {
-      name: s__('ProductAnalytics|Month'),
-      type: 'category',
-    },
-  },
   LEARN_MORE_URL: helpPagePath('/user/product_analytics/index', {
     anchor: 'product-analytics-usage-quota',
   }),
@@ -106,7 +98,7 @@ export default {
 </script>
 <template>
   <section class="gl-mt-5 gl-mb-7">
-    <h2 class="gl-font-lg">{{ s__('ProductAnalytics|Usage by month') }}</h2>
+    <h2>{{ s__('Analytics|Overview') }}</h2>
     <p>
       <gl-sprintf
         :message="
@@ -124,6 +116,7 @@ export default {
         </template>
       </gl-sprintf>
     </p>
+
     <gl-alert v-if="error" variant="danger" :dismissible="false">
       {{
         s__(
@@ -131,9 +124,19 @@ export default {
         )
       }}
     </gl-alert>
-    <gl-skeleton-loader v-else-if="isLoading" :lines="3" />
     <template v-else>
-      <gl-area-chart :data="chartData" :option="$options.CHART_OPTIONS" />
+      <product-analytics-group-usage-overview
+        v-if="showUsageOverview"
+        :events-used="eventsUsed"
+        :stored-events-limit="storedEventsLimit"
+        :is-loading="isLoading"
+      />
+
+      <h2>{{ s__('Analytics|Usage breakdown') }}</h2>
+      <product-analytics-group-monthly-usage-chart
+        :is-loading="isLoading"
+        :monthly-totals="monthlyTotals"
+      />
     </template>
   </section>
 </template>
diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview.vue b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview.vue
new file mode 100644
index 0000000000000000000000000000000000000000..84b477d0520d425efb2bfa61ef10abf116cf9540
--- /dev/null
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview.vue
@@ -0,0 +1,64 @@
+<script>
+import { formatNumber, s__ } from '~/locale';
+import { formatDate } from '~/lib/utils/datetime/date_format_utility';
+import { SHORT_DATE_FORMAT } from '~/vue_shared/constants';
+
+import StatisticsCard from '../../../components/statistics_card.vue';
+import { getCurrentMonth } from '../utils';
+
+export default {
+  name: 'ProductAnalyticsGroupUsageOverview',
+  components: { StatisticsCard },
+  props: {
+    eventsUsed: {
+      type: Number,
+      required: false,
+      default: null,
+    },
+    storedEventsLimit: {
+      type: Number,
+      required: false,
+      default: null,
+    },
+    isLoading: {
+      type: Boolean,
+      required: false,
+    },
+  },
+  computed: {
+    description() {
+      const currentMonth = getCurrentMonth();
+      return s__(`Analytics|Events received since ${formatDate(currentMonth, SHORT_DATE_FORMAT)}`);
+    },
+    eventsUsedPercentage() {
+      if (!this.storedEventsLimit) {
+        return 100;
+      }
+
+      const used = Math.floor((this.eventsUsed / this.storedEventsLimit) * 100);
+
+      return Math.min(used, 100);
+    },
+    formattedEventsUsed() {
+      return formatNumber(this.eventsUsed);
+    },
+    formattedStoredEventsLimit() {
+      return formatNumber(this.storedEventsLimit);
+    },
+    showStatisticsCard() {
+      return this.isLoading || this.storedEventsLimit !== null;
+    },
+  },
+};
+</script>
+
+<template>
+  <statistics-card
+    v-if="showStatisticsCard"
+    :loading="isLoading"
+    :usage-value="formattedEventsUsed"
+    :total-value="formattedStoredEventsLimit"
+    :description="description"
+    :percentage="eventsUsedPercentage"
+  />
+</template>
diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_usage_quota_app.vue b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_usage_quota_app.vue
index 054b7576fde0e6f3018f9ea378af7b453d834137..efde40163f8868de9f58b89d46e31441dc5ecaf2 100644
--- a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_usage_quota_app.vue
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/product_analytics_usage_quota_app.vue
@@ -3,7 +3,7 @@ import { GlEmptyState } from '@gitlab/ui';
 
 import { helpPagePath } from '~/helpers/help_page_helper';
 
-import ProductAnalyticsGroupUsage from './product_analytics_group_usage.vue';
+import ProductAnalyticsGroupUsage from './group_usage/product_analytics_group_usage.vue';
 import ProductAnalyticsProjectsUsage from './projects_usage/product_analytics_projects_usage.vue';
 
 export default {
diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/utils.js b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/utils.js
index 77181eeb5c1ab72d99d1cad0adbd5435631d0006..142af323473e217b718a4c15293148a984976251 100644
--- a/ee/app/assets/javascripts/usage_quotas/product_analytics/components/utils.js
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/components/utils.js
@@ -24,6 +24,15 @@ export const projectsUsageDataValidator = (items) => {
   return Array.isArray(items) && items.every(isValidProject);
 };
 
+export const monthlyTotalsValidator = (items) => {
+  return (
+    Array.isArray(items) &&
+    items.every(
+      ([monthLabel, count]) => typeof monthLabel === 'string' && typeof count === 'number',
+    )
+  );
+};
+
 export const getCurrentMonth = () => {
   return dateAtFirstDayOfMonth(new Date());
 };
@@ -44,6 +53,10 @@ export const findPreviousMonthUsage = (project) => {
   return findMonthsUsage(project, 1);
 };
 
+const formatMonthLabel = (date) => {
+  return formatDate(date, 'mmm yyyy');
+};
+
 /**
  * Maps projects into an array of monthLabel, numEvents pairs.
  */
@@ -60,5 +73,11 @@ export const mapMonthlyTotals = (projects) => {
   return Array.from(Object.entries(monthlyTotals))
     .map(([timestampString, count]) => [Number(timestampString), count])
     .sort(([timestampA], [timestampB]) => timestampA - timestampB)
-    .map(([timestamp, count]) => [formatDate(new Date(timestamp), 'mmm yyyy'), count]);
+    .map(([timestamp, count]) => [formatMonthLabel(new Date(timestamp)), count]);
+};
+
+export const findCurrentMonthEventsUsed = (monthlyTotals) => {
+  const currentMonthLabel = formatMonthLabel(getCurrentMonth());
+
+  return monthlyTotals?.find(([dateLabel]) => dateLabel === currentMonthLabel)?.at(1);
 };
diff --git a/ee/app/assets/javascripts/usage_quotas/product_analytics/graphql/queries/get_group_product_analytics_usage.query.graphql b/ee/app/assets/javascripts/usage_quotas/product_analytics/graphql/queries/get_group_product_analytics_usage.query.graphql
index 0eaba32c8ca544765bbd43d5f3ace72afcbaf7c5..d214020dfe45dac5c2f7ee4082d8b41677992239 100644
--- a/ee/app/assets/javascripts/usage_quotas/product_analytics/graphql/queries/get_group_product_analytics_usage.query.graphql
+++ b/ee/app/assets/javascripts/usage_quotas/product_analytics/graphql/queries/get_group_product_analytics_usage.query.graphql
@@ -1,6 +1,7 @@
 query getGroupProductAnalyticsUsage($namespacePath: ID!, $monthSelection: [MonthSelectionInput!]!) {
   group(fullPath: $namespacePath) {
     id
+    productAnalyticsStoredEventsLimit
     projects(includeSubgroups: true) {
       nodes {
         id
diff --git a/ee/app/controllers/ee/groups/usage_quotas_controller.rb b/ee/app/controllers/ee/groups/usage_quotas_controller.rb
index f1b5891b290c00fc72ad4cec5c0cb9b5b691eb21..06f7abd4a2d72270e50ada787fa5e88b07676db5 100644
--- a/ee/app/controllers/ee/groups/usage_quotas_controller.rb
+++ b/ee/app/controllers/ee/groups/usage_quotas_controller.rb
@@ -16,6 +16,7 @@ module UsageQuotasController
           push_frontend_feature_flag(:limited_access_modal)
           push_frontend_feature_flag(:enable_add_on_users_filtering, group)
           push_frontend_feature_flag(:product_analytics_usage_quota_annual_data, group)
+          push_frontend_feature_flag(:product_analytics_billing, type: :wip)
         end
       end
 
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart_spec.js b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..24c4bb806dcc7e0a21ec69bf7c2634637d6e3854
--- /dev/null
+++ b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart_spec.js
@@ -0,0 +1,64 @@
+import { GlSkeletonLoader } from '@gitlab/ui';
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import ProductAnalyticsGroupMonthlyUsageChart from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart.vue';
+
+describe('ProductAnalyticsGroupMonthlyUsageChart', () => {
+  /** @type {import('helpers/vue_test_utils_helper').ExtendedWrapper} */
+  let wrapper;
+
+  const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+  const findChart = () => wrapper.findComponent(GlAreaChart);
+
+  const createComponent = (props = {}) => {
+    wrapper = shallowMountExtended(ProductAnalyticsGroupMonthlyUsageChart, {
+      propsData: {
+        ...props,
+      },
+    });
+  };
+
+  it('renders a section header', () => {
+    createComponent();
+
+    expect(wrapper.text()).toContain('Usage by month');
+  });
+
+  describe('when loading', () => {
+    beforeEach(() => {
+      createComponent({ isLoading: true });
+    });
+
+    it('renders the loading state', () => {
+      expect(findSkeletonLoader().exists()).toBe(true);
+    });
+
+    it('does not render the chart', () => {
+      expect(findChart().exists()).toBe(false);
+    });
+  });
+
+  describe('once loaded', () => {
+    const monthlyTotals = [['Nov 2023', 1234]];
+
+    beforeEach(() => {
+      createComponent({ isLoading: false, monthlyTotals });
+    });
+
+    it('does not render the loading state', () => {
+      expect(findSkeletonLoader().exists()).toBe(false);
+    });
+
+    it('renders the chart', () => {
+      expect(findChart().props()).toMatchObject({
+        data: [
+          {
+            name: 'Analytics events by month',
+            data: [['Nov 2023', 1234]],
+          },
+        ],
+      });
+    });
+  });
+});
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview_spec.js b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d4933e0af4e079747747aa90ea17763b2825e71
--- /dev/null
+++ b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview_spec.js
@@ -0,0 +1,68 @@
+import { useFakeDate } from 'helpers/fake_date';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import ProductAnalyticsGroupUsageOverview from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview.vue';
+import StatisticsCard from 'ee/usage_quotas/components/statistics_card.vue';
+
+describe('ProductAnalyticsGroupUsageOverview', () => {
+  /** @type {import('helpers/vue_test_utils_helper').ExtendedWrapper} */
+  let wrapper;
+
+  const mockNow = '2023-01-15T12:00:00Z';
+  useFakeDate(mockNow);
+
+  const findStatisticsCard = () => wrapper.findComponent(StatisticsCard);
+
+  const createWrapper = (props = {}) => {
+    wrapper = shallowMountExtended(ProductAnalyticsGroupUsageOverview, {
+      propsData: {
+        ...props,
+      },
+    });
+  };
+
+  it('should render loading indicators', () => {
+    createWrapper({ isLoading: true });
+
+    expect(findStatisticsCard().props('loading')).toBe(true);
+  });
+
+  describe('once loaded', () => {
+    describe('with no events limit set', () => {
+      beforeEach(() => {
+        createWrapper({
+          isLoading: false,
+          eventsUsed: 123456,
+          storedEventsLimit: null,
+        });
+      });
+
+      it('should not render statistics card', () => {
+        expect(findStatisticsCard().exists()).toBe(false);
+      });
+    });
+
+    describe('with an events limit set', () => {
+      beforeEach(() => {
+        createWrapper({
+          isLoading: false,
+          eventsUsed: 123456,
+          storedEventsLimit: 1000000,
+        });
+      });
+
+      it('should not render loading indicators', () => {
+        expect(findStatisticsCard().props('loading')).toBe(false);
+      });
+
+      it('should render the statistics card', () => {
+        expect(findStatisticsCard().props()).toMatchObject({
+          description: 'Events received since Jan 01, 2023',
+          percentage: 12,
+          totalValue: '1,000,000',
+          usageValue: '123,456',
+        });
+      });
+    });
+  });
+});
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_group_usage_spec.js b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_spec.js
similarity index 62%
rename from ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_group_usage_spec.js
rename to ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_spec.js
index 876186d26968c335d01a12aea80104cb5869c267..f3791eccd4ff59c91f5e41d72d227c2970a6de28 100644
--- a/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_group_usage_spec.js
+++ b/ee/spec/frontend/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_spec.js
@@ -1,21 +1,22 @@
 import Vue from 'vue';
 import VueApollo from 'vue-apollo';
-import { GlAlert, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { GlAlert, GlSprintf } from '@gitlab/ui';
 import * as Sentry from '~/sentry/sentry_browser_wrapper';
 
 import createMockApollo from 'helpers/mock_apollo_helper';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import waitForPromises from 'helpers/wait_for_promises';
 import {
-  getProjectWithYearsUsage,
   getProjectsUsageDataResponse,
   getProjectUsage,
+  getProjectWithYearsUsage,
 } from 'ee_jest/usage_quotas/product_analytics/graphql/mock_data';
 import { useFakeDate } from 'helpers/fake_date';
 
 import getGroupCurrentAndPrevProductAnalyticsUsage from 'ee/usage_quotas/product_analytics/graphql/queries/get_group_product_analytics_usage.query.graphql';
-import ProductAnalyticsGroupUsage from 'ee/usage_quotas/product_analytics/components/product_analytics_group_usage.vue';
+import ProductAnalyticsGroupUsage from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage.vue';
+import ProductAnalyticsGroupMonthlyUsageChart from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_monthly_usage_chart.vue';
+import ProductAnalyticsGroupUsageOverview from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage_overview.vue';
 
 Vue.use(VueApollo);
 
@@ -29,8 +30,8 @@ describe('ProductAnalyticsGroupUsage', () => {
   useFakeDate(mockNow);
 
   const findError = () => wrapper.findComponent(GlAlert);
-  const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
-  const findChart = () => wrapper.findComponent(GlAreaChart);
+  const findUsageOverview = () => wrapper.findComponent(ProductAnalyticsGroupUsageOverview);
+  const findChart = () => wrapper.findComponent(ProductAnalyticsGroupMonthlyUsageChart);
   const findLearnMoreLink = () => wrapper.findByTestId('product-analytics-usage-quota-learn-more');
 
   const mockProjectsUsageDataHandler = jest.fn();
@@ -62,7 +63,6 @@ describe('ProductAnalyticsGroupUsage', () => {
   it('renders a section header', () => {
     createComponent();
 
-    expect(wrapper.text()).toContain('Usage by month');
     expect(findLearnMoreLink().attributes('href')).toBe(
       '/help/user/product_analytics/index#product-analytics-usage-quota',
     );
@@ -158,12 +158,8 @@ describe('ProductAnalyticsGroupUsage', () => {
         expect(findError().exists()).toBe(false);
       });
 
-      it('renders the loading state', () => {
-        expect(findSkeletonLoader().exists()).toBe(true);
-      });
-
-      it('does not render the chart', () => {
-        expect(findChart().exists()).toBe(false);
+      it('renders the chart loading state', () => {
+        expect(findChart().props('isLoading')).toBe(true);
       });
     });
 
@@ -176,10 +172,6 @@ describe('ProductAnalyticsGroupUsage', () => {
         return waitForPromises();
       });
 
-      it('does not render the loading state', () => {
-        expect(findSkeletonLoader().exists()).toBe(false);
-      });
-
       it('does not render the chart', () => {
         expect(findChart().exists()).toBe(false);
       });
@@ -214,8 +206,8 @@ describe('ProductAnalyticsGroupUsage', () => {
           expect(findError().exists()).toBe(false);
         });
 
-        it('does not render the loading state', () => {
-          expect(findSkeletonLoader().exists()).toBe(false);
+        it('does not render the chart loading state', () => {
+          expect(findChart().props('isLoading')).toBe(false);
         });
 
         it('emits "no-projects" event', () => {
@@ -236,30 +228,22 @@ describe('ProductAnalyticsGroupUsage', () => {
           expect(findError().exists()).toBe(false);
         });
 
-        it('does not render the loading state', () => {
-          expect(findSkeletonLoader().exists()).toBe(false);
-        });
-
         it('renders the chart', () => {
           expect(findChart().props()).toMatchObject({
-            data: [
-              {
-                name: 'Analytics events by month',
-                data: [
-                  ['Feb 2022', 1],
-                  ['Mar 2022', 1],
-                  ['Apr 2022', 1],
-                  ['May 2022', 1],
-                  ['Jun 2022', 1],
-                  ['Jul 2022', 1],
-                  ['Aug 2022', 1],
-                  ['Sep 2022', 1],
-                  ['Oct 2022', 1],
-                  ['Nov 2022', 1],
-                  ['Dec 2022', 1],
-                  ['Jan 2023', 1],
-                ],
-              },
+            isLoading: false,
+            monthlyTotals: [
+              ['Feb 2022', 1],
+              ['Mar 2022', 1],
+              ['Apr 2022', 1],
+              ['May 2022', 1],
+              ['Jun 2022', 1],
+              ['Jul 2022', 1],
+              ['Aug 2022', 1],
+              ['Sep 2022', 1],
+              ['Oct 2022', 1],
+              ['Nov 2022', 1],
+              ['Dec 2022', 1],
+              ['Jan 2023', 1],
             ],
           });
         });
@@ -281,28 +265,100 @@ describe('ProductAnalyticsGroupUsage', () => {
 
         it('renders the chart with correctly summed counts', () => {
           expect(findChart().props()).toMatchObject({
-            data: [
-              {
-                name: 'Analytics events by month',
-                data: [
-                  ['Feb 2022', 2],
-                  ['Mar 2022', 2],
-                  ['Apr 2022', 2],
-                  ['May 2022', 2],
-                  ['Jun 2022', 2],
-                  ['Jul 2022', 2],
-                  ['Aug 2022', 2],
-                  ['Sep 2022', 2],
-                  ['Oct 2022', 2],
-                  ['Nov 2022', 2],
-                  ['Dec 2022', 2],
-                  ['Jan 2023', 2],
-                ],
-              },
+            isLoading: false,
+            monthlyTotals: [
+              ['Feb 2022', 2],
+              ['Mar 2022', 2],
+              ['Apr 2022', 2],
+              ['May 2022', 2],
+              ['Jun 2022', 2],
+              ['Jul 2022', 2],
+              ['Aug 2022', 2],
+              ['Sep 2022', 2],
+              ['Oct 2022', 2],
+              ['Nov 2022', 2],
+              ['Dec 2022', 2],
+              ['Jan 2023', 2],
             ],
           });
         });
       });
     });
   });
+
+  describe('usage overview', () => {
+    describe('when "productAnalyticsBilling" feature flag is disabled', () => {
+      describe('while loading', () => {
+        beforeEach(() => {
+          mockProjectsUsageDataHandler.mockResolvedValue({
+            data: getProjectsUsageDataResponse([getProjectWithYearsUsage()]),
+          });
+          createComponent({ glFeatures: { productAnalyticsBilling: false } });
+        });
+
+        it('does not render the usage overview loading state', () => {
+          expect(findUsageOverview().exists()).toBe(false);
+        });
+      });
+
+      describe('when there is data', () => {
+        beforeEach(() => {
+          mockProjectsUsageDataHandler.mockResolvedValue({
+            data: getProjectsUsageDataResponse([getProjectWithYearsUsage()]),
+          });
+          createComponent({ glFeatures: { productAnalyticsBilling: false } });
+          return waitForPromises();
+        });
+
+        it('does not render usage overview', () => {
+          expect(findUsageOverview().exists()).toBe(false);
+        });
+      });
+    });
+
+    describe('when "productAnalyticsBilling" feature flag is enabled', () => {
+      describe('while loading', () => {
+        beforeEach(() => {
+          mockProjectsUsageDataHandler.mockResolvedValue({
+            data: getProjectsUsageDataResponse([getProjectWithYearsUsage()]),
+          });
+          createComponent({ glFeatures: { productAnalyticsBilling: true } });
+        });
+
+        it('renders the usage overview loading state', () => {
+          expect(findUsageOverview().props('isLoading')).toBe(true);
+        });
+      });
+
+      describe('when there is an error', () => {
+        beforeEach(() => {
+          mockProjectsUsageDataHandler.mockRejectedValue(new Error('oh no!'));
+          createComponent({ glFeatures: { productAnalyticsBilling: true } });
+          return waitForPromises();
+        });
+
+        it('does not render usage overview', () => {
+          expect(findUsageOverview().exists()).toBe(false);
+        });
+      });
+
+      describe('when there is data', () => {
+        beforeEach(() => {
+          mockProjectsUsageDataHandler.mockResolvedValue({
+            data: getProjectsUsageDataResponse([getProjectWithYearsUsage()]),
+          });
+          createComponent({ glFeatures: { productAnalyticsBilling: true } });
+          return waitForPromises();
+        });
+
+        it('renders the usage overview', () => {
+          expect(findUsageOverview().props()).toMatchObject({
+            isLoading: false,
+            eventsUsed: 1,
+            storedEventsLimit: 1000000,
+          });
+        });
+      });
+    });
+  });
 });
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_usage_quota_app_spec.js b/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_usage_quota_app_spec.js
index de5e0a09022e960b892c82e260319f4af579e127..208fd3de27d6fd1cb7a9daf7d3a4874d653b6674 100644
--- a/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_usage_quota_app_spec.js
+++ b/ee/spec/frontend/usage_quotas/product_analytics/components/product_analytics_usage_quota_app_spec.js
@@ -2,7 +2,7 @@ import { nextTick } from 'vue';
 import { shallowMount } from '@vue/test-utils';
 import { GlEmptyState } from '@gitlab/ui';
 import ProductAnalyticsUsageQuotaApp from 'ee/usage_quotas/product_analytics/components/product_analytics_usage_quota_app.vue';
-import ProductAnalyticsGroupUsage from 'ee/usage_quotas/product_analytics/components/product_analytics_group_usage.vue';
+import ProductAnalyticsGroupUsage from 'ee/usage_quotas/product_analytics/components/group_usage/product_analytics_group_usage.vue';
 import ProductAnalyticsProjectsUsage from 'ee/usage_quotas/product_analytics/components/projects_usage/product_analytics_projects_usage.vue';
 
 describe('ProductAnalyticsUsageQuotaApp', () => {
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/components/utils_spec.js b/ee/spec/frontend/usage_quotas/product_analytics/components/utils_spec.js
index e583ff4ce694f0f168696c25e6d9502917e655be..d3e986bc9c74759fec466807353324a5b88981aa 100644
--- a/ee/spec/frontend/usage_quotas/product_analytics/components/utils_spec.js
+++ b/ee/spec/frontend/usage_quotas/product_analytics/components/utils_spec.js
@@ -3,6 +3,7 @@ import {
   findCurrentMonthUsage,
   findPreviousMonthUsage,
   mapMonthlyTotals,
+  monthlyTotalsValidator,
 } from 'ee/usage_quotas/product_analytics/components/utils';
 import {
   getProjectUsage,
@@ -113,6 +114,52 @@ describe('Product analytics usage quota component utils', () => {
     });
   });
 
+  describe('monthlyTotalsValidator', () => {
+    it('should return true for a valid array of monthly totals', () => {
+      const items = [
+        ['Nov 2023', 10],
+        ['Dec 2023', 12],
+        ['Jan 2024', 15],
+      ];
+
+      const isValid = monthlyTotalsValidator(items);
+
+      expect(isValid).toBe(true);
+    });
+
+    it('should return false if not given an array of arrays', () => {
+      const items = ['Nov 2023', 10];
+
+      const isValid = monthlyTotalsValidator(items);
+
+      expect(isValid).toBe(false);
+    });
+
+    it('should return false for an array that contains an invalid date label', () => {
+      const items = [
+        [false, 10],
+        ['12 2023', 12],
+        ['Jan 2024', 15],
+      ];
+
+      const isValid = monthlyTotalsValidator(items);
+
+      expect(isValid).toBe(false);
+    });
+
+    it('should return false for an array that contains an invalid count', () => {
+      const items = [
+        ['Nov 2023', 10],
+        ['Dec 2023', '12'],
+        ['Jan 2024', 15],
+      ];
+
+      const isValid = monthlyTotalsValidator(items);
+
+      expect(isValid).toBe(false);
+    });
+  });
+
   describe('findCurrentMonthUsage', () => {
     const mockNow = '2023-01-15T12:00:00Z';
     useFakeDate(mockNow);
diff --git a/ee/spec/frontend/usage_quotas/product_analytics/graphql/mock_data.js b/ee/spec/frontend/usage_quotas/product_analytics/graphql/mock_data.js
index 525c6ca069603e4b589f1de7260a84dc2506d25a..427d6568e7e0b6c114a1625ddb6c47c77b5f7cd4 100644
--- a/ee/spec/frontend/usage_quotas/product_analytics/graphql/mock_data.js
+++ b/ee/spec/frontend/usage_quotas/product_analytics/graphql/mock_data.js
@@ -13,6 +13,7 @@ export const getProjectUsage = ({ id, name, usage } = {}) => ({
 export const getProjectsUsageDataResponse = (projects) => ({
   group: {
     id: convertToGraphQLId(TYPENAME_GROUP, 1),
+    productAnalyticsStoredEventsLimit: 1000000,
     projects: {
       nodes: projects || [
         getProjectUsage({
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ffb0ff73aa0de9fbfdc69a1b43cdc17e7971df08..ec3aa089c6640bee4316da26c290a76857f9ff93 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5730,6 +5730,9 @@ msgstr ""
 msgid "Analytics|OS Version"
 msgstr ""
 
+msgid "Analytics|Overview"
+msgstr ""
+
 msgid "Analytics|Page Language"
 msgstr ""
 
@@ -5808,6 +5811,9 @@ msgstr ""
 msgid "Analytics|Updating visualization %{visualizationName}"
 msgstr ""
 
+msgid "Analytics|Usage breakdown"
+msgstr ""
+
 msgid "Analytics|Use the visualization designer to create custom visualizations. After you save a visualization, you can add it to a dashboard."
 msgstr ""