diff --git a/config/events/schema.json b/config/events/schema.json
index 7c5128b292a504d6a6fdeed67b86eec4e59d27ed..6e43b23bba2aa9008c746d9f458bb7c2b4a52795 100644
--- a/config/events/schema.json
+++ b/config/events/schema.json
@@ -47,33 +47,73 @@
       }
     },
     "additional_properties": {
-      "type": "object",
-      "properties": {
-        "label": {
+      "anyOf": [
+        {
+          "description": "Only base additional properties are provided",
           "type": "object",
           "properties": {
-            "description": {
-              "type": "string"
+            "label": {
+              "$ref": "#additional_prop"
+            },
+            "property": {
+              "$ref": "#additional_prop"
+            },
+            "value": {
+              "$ref": "#additional_prop"
+            }
+          },
+          "additionalProperties": {
+            "type": "null",
+            "x-error": "Either property/label or value must be used before defining other additional_properties"
+          }
+        },
+        {
+          "description": "All string-type base additional properties are provided, allowing custom properties",
+          "type": "object",
+          "properties": {
+            "label": {
+              "$ref": "#additional_prop"
+            },
+            "property": {
+              "$ref": "#additional_prop"
+            },
+            "value": {
+              "$ref": "#additional_prop"
             }
           },
           "required": [
-            "description"
+            "property",
+            "label"
           ],
-          "additionalProperties": false
+          "additionalProperties": {
+            "$ref": "#additional_prop"
+          }
         },
-        "property": {
+        {
+          "description": "All numeric-type base additional properties are provided, allowing custom properties",
           "type": "object",
           "properties": {
-            "description": {
-              "type": "string"
+            "label": {
+              "$ref": "#additional_prop"
+            },
+            "property": {
+              "$ref": "#additional_prop"
+            },
+            "value": {
+              "$ref": "#additional_prop"
             }
           },
           "required": [
-            "description"
+            "value"
           ],
-          "additionalProperties": false
-        },
-        "value": {
+          "additionalProperties": {
+            "$ref": "#additional_prop"
+          }
+        }
+      ],
+      "$defs": {
+        "additional_prop": {
+          "$anchor": "additional_prop",
           "type": "object",
           "properties": {
             "description": {
@@ -85,8 +125,7 @@
           ],
           "additionalProperties": false
         }
-      },
-      "additionalProperties": true
+      }
     },
     "iglu_schema_url": {
       "type": [
diff --git a/lib/gitlab/tracking/event_definition_validator.rb b/lib/gitlab/tracking/event_definition_validator.rb
index 2ba65a20054b78fa38bc3f4e5a679a2784874622..b0d5b8a897b392d234a15f3b873540abf6e50959 100644
--- a/lib/gitlab/tracking/event_definition_validator.rb
+++ b/lib/gitlab/tracking/event_definition_validator.rb
@@ -5,7 +5,6 @@ module Tracking
     class EventDefinitionValidator
       EVENT_SCHEMA_PATH = Rails.root.join('config/events/schema.json')
       SCHEMA = ::JSONSchemer.schema(EVENT_SCHEMA_PATH)
-      NOT_VALIDATED_PROPERTIES = [:value].freeze
 
       def initialize(definition)
         @attributes = definition.attributes
@@ -13,37 +12,6 @@ def initialize(definition)
       end
 
       def validation_errors
-        (validate_schema << validate_additional_properties).compact
-      end
-
-      private
-
-      attr_reader :attributes, :path
-
-      def validate_additional_properties
-        additional_props = attributes[:additional_properties]&.map { |k, _| k }
-
-        return unless additional_props.present?
-
-        extra_props = additional_props - Gitlab::Tracking::EventValidator::BASE_ADDITIONAL_PROPERTIES.keys
-        unused_props = prioritized_properties - additional_props
-
-        return unless extra_props.present? && unused_props.present?
-
-        <<~ERROR_MSG
-          --------------- VALIDATION ERROR ---------------
-          Definition file: #{path}
-          Error type: consider using the built-in additional properties:
-          "#{prioritized_properties.join(', ')}"
-          before adding custom extra properties: #{extra_props.join(', ')}
-        ERROR_MSG
-      end
-
-      def prioritized_properties
-        Gitlab::Tracking::EventValidator::BASE_ADDITIONAL_PROPERTIES.keys - NOT_VALIDATED_PROPERTIES
-      end
-
-      def validate_schema
         SCHEMA.validate(attributes.deep_stringify_keys).map do |error|
           <<~ERROR_MSG
             --------------- VALIDATION ERROR ---------------
@@ -51,10 +19,14 @@ def validate_schema
             Error type: #{error['type']}
             Data: #{error['data']}
             Path: #{error['data_pointer']}
-            Details: #{error['details']}
+            Details: #{error['details'] || error['error']}
           ERROR_MSG
         end
       end
+
+      private
+
+      attr_reader :attributes, :path
     end
   end
 end
diff --git a/spec/fixtures/scripts/internal_events/events/event_with_multiple_custom_properties.yml b/spec/fixtures/scripts/internal_events/events/event_with_multiple_custom_properties.yml
index 7e91c993dbfebcf6a23f7c40710df716de4a9882..552647fda285b560072eab03b1864e01af73e0b4 100644
--- a/spec/fixtures/scripts/internal_events/events/event_with_multiple_custom_properties.yml
+++ b/spec/fixtures/scripts/internal_events/events/event_with_multiple_custom_properties.yml
@@ -9,6 +9,8 @@ identifiers:
 additional_properties:
   label:
     description: TODO
+  property:
+    description: TODO
   custom_key1:
     description: The extra custom property name 1
   custom_key2:
diff --git a/spec/fixtures/scripts/internal_events/new_metrics.yml b/spec/fixtures/scripts/internal_events/new_metrics.yml
index c14c252af2871bccf3a63382e1fbb730c6cc4f49..c57d137bcaf092f04c07b55297019c18927cad48 100644
--- a/spec/fixtures/scripts/internal_events/new_metrics.yml
+++ b/spec/fixtures/scripts/internal_events/new_metrics.yml
@@ -379,6 +379,7 @@
     - "\e[B\e[B\e[B" # Arrow down to: Weekly count of unique users where label/value is...
     - "\n" # Select: Weekly count of unique users where label/value is...
     - "failure\n" # Input value for "label" filter
+    - "   \n" # Ignore whitespace to skip "property" filter
     - "metrics\n" # Input value for "custom_key1" filter
     - "\n" # Skip "custom_key2" filter
     - "30,13\n" # Input value for "custom_key3" filter
diff --git a/spec/lib/gitlab/tracking/event_definition_validator_spec.rb b/spec/lib/gitlab/tracking/event_definition_validator_spec.rb
index 6d60a2b05ae52a9c1274174cb40bbf91d3e2f1c6..1dcbede57e34bc96849c71310639cc1d429588bb 100644
--- a/spec/lib/gitlab/tracking/event_definition_validator_spec.rb
+++ b/spec/lib/gitlab/tracking/event_definition_validator_spec.rb
@@ -22,7 +22,6 @@
 
   let(:path) { File.join('events', 'issues_create.yml') }
   let(:definition) { Gitlab::Tracking::EventDefinition.new(path, attributes) }
-  # let(:yaml_content) { attributes.deep_stringify_keys.to_yaml }
 
   describe '#validate' do
     using RSpec::Parameterized::TableSyntax
@@ -69,15 +68,21 @@
       where(:label, :property, :value, :custom, :error?) do
         true  | true  | true  | true  | false
         true  | true  | true  | false | false
-        true  | true  | false | false | false
         true  | true  | false | true  | false
+        true  | true  | false | false | false
+        true  | false | true  | true  | false
+        true  | false | true  | false | false
+        true  | false | false | true  | true
         true  | false | false | false | false
-        false | true  | false | false | false
+        false | true  | true  | true  | false
         false | true  | true  | false | false
-        true  | false | true  | true  | true
-        true  | false | false | true  | true
-        false | true  | true  | true  | true
-        false | false | true  | true  | true
+        false | true  | false | true  | true
+        false | true  | false | false | false
+        false | false | true  | true  | false
+        false | false | true  | false | false
+        false | false | false | true  | true
+        false | false | false | false | false
+        nil   | nil   | nil   | nil   | false
       end
 
       with_them do
@@ -86,6 +91,8 @@
           attributes[:additional_properties][:property] = { description: "button state" } if property
           attributes[:additional_properties][:value] = { description: "package version" } if value
           attributes[:additional_properties][:custom] = { description: "custom" } if custom
+
+          attributes.delete(:additional_properties) if [label, property, value, custom].all?(&:nil?)
         end
 
         subject { described_class.new(definition).validation_errors.any? }