diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb
index 8e936782e5a60bd82548871f41660bf28c66e482..4f96cc5c89538de83dd44f51dacfde4c4254ab7e 100644
--- a/app/controllers/concerns/product_analytics_tracking.rb
+++ b/app/controllers/concerns/product_analytics_tracking.rb
@@ -29,7 +29,13 @@ def route_events_to(destinations, name, &block)
     track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
 
     if destinations.include?(:snowplow) && event_enabled?(name)
-      Gitlab::Tracking.event(self.class.to_s, name, namespace: tracking_namespace_source, user: current_user)
+      Gitlab::Tracking.event(
+        self.class.to_s,
+        name,
+        namespace: tracking_namespace_source,
+        user: current_user,
+        context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context]
+      )
     end
   end
 
@@ -49,6 +55,7 @@ def route_custom_events_to(destinations, name, action, label, &block)
       user: current_user,
       property: name,
       label: label,
+      context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context],
       **optional_arguments
     )
   end
diff --git a/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb b/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb
index b79f2806fa65c35a30b8245b9271bf1fdf166c36..bfce13199b4633df82c1a41958a2172692a6d352 100644
--- a/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/ee/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -43,7 +43,7 @@
       ['', 'dev', 'sec', 'ops'].each do |tab|
         it_behaves_like 'tracks usage event', 'i_analytics_dev_ops_adoption', tab
 
-        it_behaves_like 'Snowplow event tracking' do
+        it_behaves_like 'Snowplow event tracking with RedisHLL context' do
           subject { get :show, params: { tab: tab }, format: :html }
 
           let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/controllers/ee/search_controller_spec.rb b/ee/spec/controllers/ee/search_controller_spec.rb
index daa9dbd456b32d718658ce34b7c2bcad42b21423..acf34eb4eca9da8248944c9ab8465e152214b0ac 100644
--- a/ee/spec/controllers/ee/search_controller_spec.rb
+++ b/ee/spec/controllers/ee/search_controller_spec.rb
@@ -33,9 +33,12 @@
         it 'emits all search events' do
           subject
 
-          expect_snowplow_event(category: category, action: 'i_search_total', namespace: namespace, user: user)
-          expect_snowplow_event(category: category, action: 'i_search_paid', namespace: namespace, user: user)
-          expect_snowplow_event(category: category, action: 'i_search_advanced', namespace: namespace, user: user)
+          expect_snowplow_event(category: category, action: 'i_search_total', namespace: namespace, user: user,
+                                context: context('i_search_total'))
+          expect_snowplow_event(category: category, action: 'i_search_paid', namespace: namespace, user: user,
+                                context: context('i_search_paid'))
+          expect_snowplow_event(category: category, action: 'i_search_advanced', namespace: namespace, user: user,
+                                context: context('i_search_advanced'))
         end
       end
 
@@ -398,4 +401,10 @@ def request
       end
     end
   end
+
+  private
+
+  def context(event)
+    [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json]
+  end
 end
diff --git a/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb b/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb
index a69224a1e97ff9a058efef81e0423efe656b91ec..8083129689068eed6d6aa07447cce9083608b703 100644
--- a/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb
+++ b/ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb
@@ -59,8 +59,10 @@
       end
 
       describe 'tracking events', :snowplow do
+        let(:event) { 'g_analytics_valuestream' }
+
         it 'tracks redis hll event' do
-          expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with('g_analytics_valuestream', { values: anything })
+          expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event, { values: anything })
 
           get(:show, params: { group_id: group })
         end
@@ -68,11 +70,14 @@
         it 'tracks snowplow event' do
           get(:show, params: { group_id: group })
 
+          context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json
+
           expect_snowplow_event(
             category: 'Groups::Analytics::CycleAnalyticsController',
-            action: 'g_analytics_valuestream',
+            action: event,
             namespace: group,
-            user: user
+            user: user,
+            context: [context]
           )
         end
       end
diff --git a/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb b/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb
index 43796c72ca3ee4fdf76bc790f57a2157ffbcf1f0..1896547f2e6c2c1fdca26e311a18b362c71c6e0e 100644
--- a/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb
+++ b/ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb
@@ -74,7 +74,7 @@
         let(:target_id) { 'g_analytics_productivity' }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :show, params: { group_id: group } }
 
         let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb b/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb
index ab6635b1ee8ca01f566e218bd2df271d38dae5e1..b03a40c5a3e6d9063d5d5991f545b638dee54af4 100644
--- a/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb
+++ b/ee/spec/controllers/groups/contribution_analytics_controller_spec.rb
@@ -221,7 +221,7 @@ def create_push_event(author, project)
         let(:target_id) { 'g_analytics_contribution' }
       end
 
-      it_behaves_like 'Snowplow event tracking', overrides: { project: nil } do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context', overrides: { project: nil } do
         let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
         let(:category) { described_class.name }
         let(:action) { 'perform_analytics_usage_action' }
diff --git a/ee/spec/controllers/groups/insights_controller_spec.rb b/ee/spec/controllers/groups/insights_controller_spec.rb
index ca422c39e67352eb62c44ff579178105d75434bb..d707da29d8f79e94c0598d64b11b48de3638215d 100644
--- a/ee/spec/controllers/groups/insights_controller_spec.rb
+++ b/ee/spec/controllers/groups/insights_controller_spec.rb
@@ -138,7 +138,7 @@
           let(:target_id) { 'g_analytics_insights' }
         end
 
-        it_behaves_like 'Snowplow event tracking', overrides: { project: nil } do
+        it_behaves_like 'Snowplow event tracking with RedisHLL context', overrides: { project: nil } do
           subject { get :show, params: params.merge(group_id: parent_group.to_param) }
 
           let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
index 185711bee6dabf61ee627732964c5ff446ee105a..76d7eacf8c04dcae8590e2c6d703812a7be7fbea 100644
--- a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
+++ b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
@@ -34,7 +34,7 @@
       let(:target_id) { 'g_analytics_issues' }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       subject { get :show, params: { group_id: group.to_param } }
 
       let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb b/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb
index f98b1cd99931014d4800ebd14b0e8ce10c579e58..a7f3f4661e1ee081fc7edf559b499318d5952ab9 100644
--- a/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb
+++ b/ee/spec/controllers/projects/analytics/issues_analytics_controller_spec.rb
@@ -27,7 +27,7 @@
         let(:target_id) { 'p_analytics_issues' }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :show, params: request_params, format: :html }
 
         let(:request_params) { { namespace_id: project.namespace, project_id: project1 } }
diff --git a/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb b/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb
index be1af9230636ceea046691f0be28c96fce6465c3..3e72f24cef1690598d882bbdec91051977c370a5 100644
--- a/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb
+++ b/ee/spec/controllers/projects/analytics/merge_request_analytics_controller_spec.rb
@@ -28,7 +28,7 @@
       let(:target_id) { 'p_analytics_merge_request' }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
       let(:category) { described_class.name }
       let(:action) { 'perform_analytics_usage_action' }
diff --git a/ee/spec/controllers/projects/insights_controller_spec.rb b/ee/spec/controllers/projects/insights_controller_spec.rb
index a8a1b8eae7ecc9daaee6003f6182686bdddf8fca..f016a231e312dd7942bccb071cd3e2ce1eeaf3c0 100644
--- a/ee/spec/controllers/projects/insights_controller_spec.rb
+++ b/ee/spec/controllers/projects/insights_controller_spec.rb
@@ -107,7 +107,7 @@
         let(:target_id) { 'p_analytics_insights' }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :show, params: params, format: :html }
 
         let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb b/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb
index 1c4f402726b233803c7ddbedb3ad75046cd2d307..eb8b1aa4149d6d4e82ace3b6e9a4a8bfc0ad40d1 100644
--- a/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb
+++ b/ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb
@@ -66,7 +66,7 @@
       get :index, params: { namespace_id: project.namespace, project_id: project }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       subject(:get_index) { get :index, params: { namespace_id: project.namespace, project_id: project } }
 
       let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb b/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb
index 1858411c2a35486b3adb06cf447995706c0c90d1..80033d96c0d7c6f1f7ab7b930cf26b32636c1f7f 100644
--- a/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb
+++ b/ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb
@@ -71,7 +71,7 @@
         subject
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
         let(:category) { described_class.name }
         let(:action) { 'perform_analytics_usage_action' }
diff --git a/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb b/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb
index 076018861d09df2a034e9ea4eef79029c863eca1..1bab44ffc769137e695c493d51b6264073f60fda 100644
--- a/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb
+++ b/ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb
@@ -65,7 +65,7 @@
     let(:target_id) { 'p_analytics_code_reviews' }
   end
 
-  it_behaves_like 'Snowplow event tracking' do
+  it_behaves_like 'Snowplow event tracking with RedisHLL context' do
     subject { get :index, params: request_params, format: :html }
 
     let(:request_params) { { namespace_id: project.namespace, project_id: project } }
diff --git a/lib/gitlab/tracking/service_ping_context.rb b/lib/gitlab/tracking/service_ping_context.rb
new file mode 100644
index 0000000000000000000000000000000000000000..393cd647e7f9c44b2250b5b0d14dfe6f980d28f6
--- /dev/null
+++ b/lib/gitlab/tracking/service_ping_context.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Tracking
+    class ServicePingContext
+      SCHEMA_URL = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0'
+      ALLOWED_SOURCES = %i[redis_hll].freeze
+
+      def initialize(data_source:, event:)
+        unless ALLOWED_SOURCES.include?(data_source)
+          raise ArgumentError, "#{data_source} is not acceptable data source for ServicePingContext"
+        end
+
+        @payload = {
+          data_source: data_source,
+          event_name: event
+        }
+      end
+
+      def to_context
+        SnowplowTracker::SelfDescribingJson.new(SCHEMA_URL, @payload)
+      end
+    end
+  end
+end
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb
index 766073977c6d69c4b4892ffc5c5e2c9522db6dc5..50626a5da912cca6902b4a1a5f33a73d1e4062b7 100644
--- a/spec/controllers/admin/cohorts_controller_spec.rb
+++ b/spec/controllers/admin/cohorts_controller_spec.rb
@@ -14,7 +14,7 @@
       let(:target_id) { 'i_analytics_cohorts' }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       subject { get :index }
 
       let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
index 5d7a7e089aa8952e127edb088010ac371e2004f7..52a46b5e99ac4fad0d78ff2b421e01feac45d20e 100644
--- a/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -29,7 +29,7 @@
         let(:request_params) { { tab: 'devops-score' } }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :show, format: :html }
 
         let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/admin/usage_trends_controller_spec.rb b/spec/controllers/admin/usage_trends_controller_spec.rb
index 356f603bf57a0502042c539fba08c36a168cfef5..87cf8988b4e4b97f80e4aa37541a69bae56848ac 100644
--- a/spec/controllers/admin/usage_trends_controller_spec.rb
+++ b/spec/controllers/admin/usage_trends_controller_spec.rb
@@ -14,7 +14,7 @@
       let(:target_id) { 'i_analytics_instance_statistics' }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       subject { get :index }
 
       let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
diff --git a/spec/controllers/concerns/product_analytics_tracking_spec.rb b/spec/controllers/concerns/product_analytics_tracking_spec.rb
index 2e734d81ea003641309a690d51b41128b0eb5d25..f85b6806f301cd6851dad89a1554a0763235909a 100644
--- a/spec/controllers/concerns/product_analytics_tracking_spec.rb
+++ b/spec/controllers/concerns/product_analytics_tracking_spec.rb
@@ -55,11 +55,19 @@ def expect_tracking(user: self.user)
     expect(Gitlab::UsageDataCounters::HLLRedisCounter).to have_received(:track_event)
                                                             .with('g_analytics_valuestream', values: instance_of(String))
 
+    expect_snowplow_tracking(user)
+  end
+
+  def expect_snowplow_tracking(user)
+    context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'g_analytics_valuestream')
+                                                  .to_context.to_json
+
     expect_snowplow_event(
       category: anything,
       action: 'g_analytics_valuestream',
       namespace: group,
-      user: user
+      user: user,
+      context: [context]
     )
   end
 
@@ -160,12 +168,7 @@ def expect_no_tracking
       get :show, params: { id: 2 }
 
       expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
-      expect_snowplow_event(
-        category: anything,
-        action: 'g_analytics_valuestream',
-        namespace: group,
-        user: nil
-      )
+      expect_snowplow_tracking(nil)
     end
   end
 end
diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb
index f5dd8abd67b9fdc37a03b8acb54371f5e31078f9..034e6104f99a5df5b2e37e853842dc0e9621f9ac 100644
--- a/spec/controllers/projects/cycle_analytics_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb
@@ -31,7 +31,7 @@
       let(:target_id) { 'p_analytics_valuestream' }
     end
 
-    it_behaves_like 'Snowplow event tracking' do
+    it_behaves_like 'Snowplow event tracking with RedisHLL context' do
       subject { get :show, params: request_params, format: :html }
 
       let(:request_params) { { namespace_id: project.namespace, project_id: project } }
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index 9227c7dd70a985beaf782265ad90c1ed8d0713e2..3dfc22927cfd49386fac11fa3d36c9d78c7499ec 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -90,7 +90,7 @@
         let(:target_id) { 'p_analytics_repo' }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject do
           sign_in(user)
           get :charts, params: request_params, format: :html
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index b9acaf658926e7b7133bd270e6219e5d37db347b..6e2de0c4d57e58cdfb39f8a09422b485d4c2e230 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -859,7 +859,7 @@ def get_stage(name, params = {})
         let(:target_id) { ['p_analytics_pipelines', tab[:event]] }
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :charts, params: request_params, format: :html }
 
         let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 4131bd148dad211d3bd37e6b1332d65a526051cd..7ab66b04a6e537ff3bd0918c0d715cda787956e6 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -218,7 +218,7 @@
         end
       end
 
-      it_behaves_like 'Snowplow event tracking' do
+      it_behaves_like 'Snowplow event tracking with RedisHLL context' do
         subject { get :show, params: { group_id: namespace.id, scope: 'blobs', search: 'term' } }
 
         let(:project) { nil }
diff --git a/spec/lib/gitlab/tracking/service_ping_context_spec.rb b/spec/lib/gitlab/tracking/service_ping_context_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d70dfaa4e0b51b2ce2ef15f182667bdbcb15781c
--- /dev/null
+++ b/spec/lib/gitlab/tracking/service_ping_context_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Tracking::ServicePingContext do
+  describe '#init' do
+    it 'does not accept unsupported data sources' do
+      expect { described_class.new(data_source: :random, event: 'event a') }.to raise_error(ArgumentError)
+    end
+  end
+
+  describe '#to_context' do
+    let(:subject) { described_class.new(data_source: :redis_hll, event: 'sample_event') }
+
+    it 'contains event_name' do
+      expect(subject.to_context.to_json.dig(:data, :event_name)).to eq('sample_event')
+    end
+  end
+end
diff --git a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
index 4af3c0cc6cc2e93ec3b517e1abfd5ab4c076320c..6749ebd471f1daff7b1325d4e062137e2f8bd503 100644
--- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
+++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
@@ -32,7 +32,8 @@
       user: try(:user),
       project: try(:project),
       label: try(:label),
-      property: try(:property)
+      property: try(:property),
+      context: try(:context)
     }.merge(overrides).compact.merge(extra)
 
     subject
@@ -40,3 +41,12 @@
     expect_snowplow_event(**params)
   end
 end
+
+RSpec.shared_examples 'Snowplow event tracking with RedisHLL context' do |overrides: {}|
+  it_behaves_like 'Snowplow event tracking', overrides: overrides do
+    let(:context) do
+      event = try(:property) || action
+      [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: event).to_context.to_json]
+    end
+  end
+end