diff --git a/config/events/g_project_management_issue_created.yml b/config/events/g_project_management_issue_created.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0fe5dd5f82e447f27703b55d460cbfa5ee25b0db
--- /dev/null
+++ b/config/events/g_project_management_issue_created.yml
@@ -0,0 +1,24 @@
+---
+description: An issue has been created
+category: InternalEventTracking
+action: g_project_management_issue_created
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+  - namespace
+  - project
+  - user
+product_section: dev
+product_stage: plan
+product_group: project_management
+milestone: "16.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123184
+distributions:
+  - ce
+  - ee
+tiers:
+  - free
+  - premium
+  - ultimate
diff --git a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
index 31f090e0f5163ca5b1aab12414fb2ec9630f0e08..429ca636b2cede0a605bd441e4ca32bfc5effed0 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -38,8 +38,7 @@ module IssueActivityUniqueCounter
 
       class << self
         def track_issue_created_action(author:, namespace:)
-          track_snowplow_action(ISSUE_CREATED, author, namespace)
-          track_unique_action(ISSUE_CREATED, author)
+          track_internal_action(ISSUE_CREATED, author, namespace)
         end
 
         def track_issue_title_changed_action(author:, project:)
@@ -180,14 +179,7 @@ def track_issue_design_comment_removed_action(author:, project:)
         private
 
         def track_snowplow_action(event_name, author, container)
-          namespace, project = case container
-                               when Project
-                                 [container.namespace, container]
-                               when Namespaces::ProjectNamespace
-                                 [container.parent, container.project]
-                               else
-                                 [container, nil]
-                               end
+          namespace, project = get_params_from_container(container)
 
           return unless author
 
@@ -208,6 +200,30 @@ def track_unique_action(event_name, author)
 
           Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: author.id)
         end
+
+        def track_internal_action(event_name, author, container)
+          return unless author
+
+          namespace, project = get_params_from_container(container)
+
+          Gitlab::InternalEvents.track_event(
+            event_name,
+            user_id: author.id,
+            project_id: project&.id,
+            namespace_id: namespace&.id
+          )
+        end
+
+        def get_params_from_container(container)
+          case container
+          when Project
+            [container.namespace, container]
+          when Namespaces::ProjectNamespace
+            [container.parent, container.project]
+          else
+            [container, nil]
+          end
+        end
       end
     end
   end
diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
index ba83d979cadc199d5a3d51ee8aaaab1ca4792873..50e20e4fbcf4f81b023ee90a07d6f1143ecf17f1 100644
--- a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
@@ -66,7 +66,7 @@ def track_action(params)
   end
 
   context 'for Issue created actions' do
-    it_behaves_like 'tracked issuable snowplow and service ping events with project' do
+    it_behaves_like 'tracked issuable internal event with project' do
       let(:action) { described_class::ISSUE_CREATED }
       let(:original_params) { { namespace: project.project_namespace.reload } }
 
diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
index 25c57aa00c6e5724f3892e635171d5c3ca6c40e6..53eee62b3866d11a6f7571b99fbf1f9b7e7f6629 100644
--- a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
@@ -54,11 +54,6 @@
 
     let(:merge_request) { create(:merge_request) }
     let(:target_project) { merge_request.target_project }
-    let(:fake_tracker) { instance_spy(Gitlab::Tracking::Destinations::Snowplow) }
-
-    before do
-      allow(Gitlab::Tracking).to receive(:tracker).and_return(fake_tracker)
-    end
 
     it_behaves_like 'a tracked merge request unique event' do
       let(:action) { described_class::MR_USER_CREATE_ACTION }
@@ -68,36 +63,10 @@
       let(:action) { described_class::MR_CREATE_ACTION }
     end
 
-    it 'logs to Snowplow', :aggregate_failures do
-      # This logic should be extracted to shared_examples
-      namespace = target_project.namespace
-
-      expect(Gitlab::Tracking::StandardContext)
-        .to receive(:new)
-          .with(
-            project_id: target_project.id,
-            user_id: user.id,
-            namespace_id: namespace.id,
-            plan_name: namespace.actual_plan_name
-          )
-          .and_call_original
-
-      expect(Gitlab::Tracking::ServicePingContext)
-        .to receive(:new)
-          .with(data_source: :redis_hll, event: described_class::MR_USER_CREATE_ACTION)
-          .and_call_original
-
-      expect(fake_tracker).to receive(:event)
-        .with(
-          'InternalEventTracking',
-          described_class::MR_USER_CREATE_ACTION,
-          context: [
-            an_instance_of(SnowplowTracker::SelfDescribingJson),
-            an_instance_of(SnowplowTracker::SelfDescribingJson)
-          ]
-        )
-        .exactly(:once)
-      subject
+    it_behaves_like 'internal event tracking' do
+      let(:action) { described_class::MR_USER_CREATE_ACTION }
+      let(:project) { target_project }
+      let(:namespace) { project.namespace }
     end
   end
 
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index ee47f90fb406159bda3565dfe9954c55e5f65331..4cd73cd3fe6f1e086cbc771d72a1308e4ce8a0cc 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -338,11 +338,13 @@
         create(:issue)
       end
 
-      it_behaves_like 'issue_edit snowplow tracking' do
+      it_behaves_like 'internal event tracking' do
         let(:issue) { create(:issue) }
         let(:project) { issue.project }
-        let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CREATED }
         let(:user) { issue.author }
+        let(:action) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CREATED }
+        let(:namespace) { project.namespace }
+
         subject(:service_action) { issue }
       end
     end
diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb
index e0ec54fd5ff92a762b06415219bee59cf48d8935..bf43a2032e73680868ac69b8403a2fc76b93f977 100644
--- a/spec/models/work_item_spec.rb
+++ b/spec/models/work_item_spec.rb
@@ -212,11 +212,13 @@
         create(:work_item)
       end
 
-      it_behaves_like 'issue_edit snowplow tracking' do
+      it_behaves_like 'internal event tracking' do
         let(:work_item) { create(:work_item) }
-        let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CREATED }
+        let(:action) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CREATED }
         let(:project) { work_item.project }
         let(:user) { work_item.author }
+        let(:namespace) { project.namespace }
+
         subject(:service_action) { work_item }
       end
     end
diff --git a/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb b/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e2a4fb3136189b974a8cfcc7cfc54d8b24275c8b
--- /dev/null
+++ b/spec/support/shared_examples/controllers/internal_event_tracking_examples.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+# Requires a context containing:
+# - subject
+# - action
+# - user
+# Optionally, the context can contain:
+# - project
+# - namespace
+
+RSpec.shared_examples 'internal event tracking' do
+  let(:fake_tracker) { instance_spy(Gitlab::Tracking::Destinations::Snowplow) }
+  let(:namespace) { nil }
+  let(:proejct) { nil }
+
+  before do
+    allow(Gitlab::Tracking).to receive(:tracker).and_return(fake_tracker)
+
+    allow(Gitlab::Tracking::StandardContext).to receive(:new).and_call_original
+    allow(Gitlab::Tracking::ServicePingContext).to receive(:new).and_call_original
+  end
+
+  it 'logs to Snowplow', :aggregate_failures do
+    subject
+
+    expect(Gitlab::Tracking::StandardContext)
+      .to have_received(:new)
+        .with(
+          project_id: project&.id,
+          user_id: user.id,
+          namespace_id: namespace&.id,
+          plan_name: namespace&.actual_plan_name
+        )
+
+    expect(Gitlab::Tracking::ServicePingContext)
+      .to have_received(:new)
+        .with(data_source: :redis_hll, event: action)
+
+    expect(fake_tracker).to have_received(:event)
+      .with(
+        'InternalEventTracking',
+        action,
+        context: [
+          an_instance_of(SnowplowTracker::SelfDescribingJson),
+          an_instance_of(SnowplowTracker::SelfDescribingJson)
+        ]
+      )
+      .exactly(:once)
+  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 ba00e3e06105f7bf216f4c94e929a5a18a113d5e..3d3b619451d5b22cdb218bb32c1512ae1005d82c 100644
--- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
+++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
@@ -6,7 +6,7 @@
 # - category
 # - action
 # - namespace
-# Optionaly, the context can contain:
+# Optionally, the context can contain:
 # - project
 # - property
 # - user
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
index 169fceced7a85f121fc22a31ca7fefdd5cf0c6a9..9dc185553402a0f7ebc14ffd57421eba7c44917a 100644
--- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
@@ -1,6 +1,6 @@
 # frozen_string_literal: true
 
-RSpec.shared_examples 'tracked issuable snowplow and service ping events for given event params' do
+RSpec.shared_examples 'tracked issuable events' do
   before do
     stub_application_setting(usage_ping_enabled: true)
   end
@@ -21,6 +21,10 @@ def count_unique(date_from: Date.today.beginning_of_week, date_to: 1.week.from_n
   it 'does not track edit actions if author is not present' do
     expect(track_action({ author: nil }.merge(track_params))).to be_nil
   end
+end
+
+RSpec.shared_examples 'tracked issuable snowplow and service ping events for given event params' do
+  it_behaves_like 'tracked issuable events'
 
   it 'emits snowplow event' do
     track_action({ author: user1 }.merge(track_params))
@@ -29,6 +33,23 @@ def count_unique(date_from: Date.today.beginning_of_week, date_to: 1.week.from_n
   end
 end
 
+RSpec.shared_examples 'tracked issuable internal event for given event params' do
+  it_behaves_like 'tracked issuable events'
+
+  it_behaves_like 'internal event tracking' do
+    subject(:track_event) { track_action({ author: user1 }.merge(track_params)) }
+
+    let(:user) { user1 }
+    let(:namespace) { project&.namespace }
+  end
+end
+
+RSpec.shared_examples 'tracked issuable internal event with project' do
+  it_behaves_like 'tracked issuable internal event for given event params' do
+    let(:track_params) { original_params || { project: project } }
+  end
+end
+
 RSpec.shared_examples 'tracked issuable snowplow and service ping events with project' do
   it_behaves_like 'tracked issuable snowplow and service ping events for given event params' do
     let(:context) do