docusaurus-plugin-generate-schema-docs 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +28 -0
  2. package/__tests__/ExampleDataLayer.test.js +13 -0
  3. package/__tests__/__fixtures__/static/schemas/anchor/parent-event-anchor.json +29 -0
  4. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/add-to-cart-event.json +45 -0
  5. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/choice-event.json +78 -0
  6. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/complex-event.json +193 -0
  7. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/components/dataLayer.json +56 -0
  8. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/components/product.json +126 -0
  9. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/purchase-event.json +73 -0
  10. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/root-any-of-event.json +40 -0
  11. package/__tests__/__fixtures__/validateSchemas/complex-validation/events/root-choice-event.json +54 -0
  12. package/__tests__/__snapshots__/generateEventDocs.anchor.test.js.snap +79 -0
  13. package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +8 -2
  14. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +20 -5
  15. package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +8 -2
  16. package/__tests__/components/PropertiesTable.test.js +34 -1
  17. package/__tests__/components/PropertyRow.test.js +5 -5
  18. package/__tests__/generateEventDocs.anchor.test.js +71 -0
  19. package/__tests__/helpers/example-helper.test.js +71 -0
  20. package/__tests__/helpers/getConstraints.test.js +72 -27
  21. package/__tests__/helpers/schemaToTableData.test.js +28 -33
  22. package/__tests__/helpers/validator.test.js +115 -0
  23. package/__tests__/validateSchemas-integration.test.js +29 -0
  24. package/__tests__/validateSchemas.test.js +18 -102
  25. package/components/ExampleDataLayer.js +14 -5
  26. package/components/PropertiesTable.js +22 -7
  27. package/components/PropertiesTable.module.css +27 -0
  28. package/components/PropertyRow.js +24 -25
  29. package/components/SchemaRows.css +6 -0
  30. package/components/SchemaViewer.js +2 -2
  31. package/components/WordWrapButton.js +31 -0
  32. package/components/wordWrapButton.module.css +8 -0
  33. package/generateEventDocs.js +2 -1
  34. package/helpers/buildExampleFromSchema.js +49 -52
  35. package/helpers/example-helper.js +41 -0
  36. package/helpers/file-system.js +1 -2
  37. package/helpers/getConstraints.js +1 -0
  38. package/helpers/schema-doc-template.js +8 -1
  39. package/helpers/schema-processing.js +2 -15
  40. package/helpers/schemaToExamples.js +46 -74
  41. package/helpers/schemaToTableData.js +4 -3
  42. package/helpers/validator.js +108 -0
  43. package/index.js +18 -9
  44. package/package.json +1 -2
  45. package/validateSchemas.js +70 -53
  46. package/__tests__/helpers/loadSchema.test.js +0 -20
  47. package/helpers/loadSchema.js +0 -11
package/README.md CHANGED
@@ -29,6 +29,7 @@ npm install --save docusaurus-plugin-generate-schema-docs
29
29
  'docusaurus-plugin-generate-schema-docs',
30
30
  {
31
31
  // Options if any
32
+ dataLayerName: 'customDataLayer',
32
33
  },
33
34
  ],
34
35
  ],
@@ -36,6 +37,8 @@ npm install --save docusaurus-plugin-generate-schema-docs
36
37
  };
37
38
  ```
38
39
 
40
+ The `dataLayerName` option allows you to customize the name of the data layer variable in the generated examples. If not provided, it defaults to `dataLayer`.
41
+
39
42
  2. Place your JSON schemas in the `schemas` directory at the root of your project.
40
43
 
41
44
  ## CLI Commands
@@ -76,6 +79,31 @@ The plugin reads your JSON schemas, dereferences any `$ref` properties, and merg
76
79
 
77
80
  The validation script builds an example from each schema and validates it against the schema itself, ensuring your examples are always in sync with your schemas.
78
81
 
82
+ ## Schema Composition (anyOf, oneOf)
83
+
84
+ The plugin has special handling for `anyOf` and `oneOf` keywords in your JSON schemas.
85
+
86
+ ### `anyOf`
87
+
88
+ When `anyOf` is used, the plugin will render a dropdown menu in the documentation that allows users to switch between the different sub-schemas. This is useful for representing properties that can have multiple different structures.
89
+
90
+ ### `oneOf`
91
+
92
+ Similar to `anyOf`, `oneOf` will also render a dropdown menu.
93
+
94
+ #### `oneOf` at the Root Level
95
+
96
+ A special behavior is triggered when `oneOf` is used at the root level of a schema file. If a schema's top-level definition is a `oneOf` array, the plugin will generate a directory structure that reflects the choices.
97
+
98
+ For example, given a schema `my-event.json` with a `oneOf` at the root, where each item in the `oneOf` array is a reference to another schema file (e.g., `option-a.json`, `option-b.json`), the plugin will generate the following structure:
99
+
100
+ - `docs/events/my-event/`: A directory for the parent schema.
101
+ - `docs/events/my-event/index.mdx`: An index page for `my-event`.
102
+ - `docs/events/my-event/option-a.mdx`: A page for the first option.
103
+ - `docs/events/my-event/option-b.mdx`: A page for the second option.
104
+
105
+ This creates a nested navigation structure in Docusaurus, which is useful for grouping related events or entities under a single menu item.
106
+
79
107
  ## Versioning
80
108
 
81
109
  This plugin supports documentation and schema versioning, integrated with Docusaurus's native versioning system.
@@ -68,6 +68,19 @@ describe('ExampleDataLayer', () => {
68
68
  // Let snapshot testing verify the complex content of each tab
69
69
  expect(container).toMatchSnapshot();
70
70
  });
71
+
72
+ it('should use the provided dataLayerName', () => {
73
+ const schema = {
74
+ type: 'object',
75
+ properties: {
76
+ event: { type: 'string', examples: ['test_event'] },
77
+ },
78
+ };
79
+ const { getByText } = render(
80
+ <ExampleDataLayer schema={schema} dataLayerName="customDataLayer" />,
81
+ );
82
+ expect(getByText(/window.customDataLayer.push/)).toBeInTheDocument();
83
+ });
71
84
  });
72
85
 
73
86
  describe('findClearableProperties', () => {
@@ -0,0 +1,29 @@
1
+ {
2
+ "$id": "https://example.com/parent-event-anchor.json",
3
+ "title": "Parent Event Anchor",
4
+ "description": "This is a parent event with oneOf.",
5
+ "type": "object",
6
+ "oneOf": [
7
+ {
8
+ "title": "Child Event Anchor",
9
+ "description": "This is a child event with an anchor.",
10
+ "$anchor": "child-event-with-anchor",
11
+ "type": "object",
12
+ "properties": {
13
+ "property_a": {
14
+ "type": "string"
15
+ }
16
+ }
17
+ },
18
+ {
19
+ "title": "Child Event Title",
20
+ "description": "This is a child event with only a title.",
21
+ "type": "object",
22
+ "properties": {
23
+ "property_b": {
24
+ "type": "string"
25
+ }
26
+ }
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/add-to-cart-event.json",
4
+ "title": "Add to Cart Event",
5
+ "description": "An add_to_cart event fires when a user adds one or more items to their shopping cart. Based on Google Analytics 4 ecommerce event specifications.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "description": "Defines the structure of the event. This can be used to validate an event against the schema provided.",
10
+ "const": "events/add-to-cart-event.json",
11
+ "type": "string"
12
+ },
13
+ "event": {
14
+ "type": "string",
15
+ "const": "add_to_cart",
16
+ "description": "The name of the event indicating a add_to_cart has occurred."
17
+ },
18
+ "ecommerce": {
19
+ "type": "object",
20
+ "description": "Ecommerce related data for the purchase event.",
21
+ "properties": {
22
+ "value": {
23
+ "type": "number",
24
+ "description": "The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.",
25
+ "examples": [30.03, 99.99, 45.5]
26
+ },
27
+ "currency": {
28
+ "type": "string",
29
+ "description": "The currency of the items in ISO 4217 three-letter format. Required when value is set.",
30
+ "examples": ["USD", "EUR", "GBP"]
31
+ },
32
+ "items": {
33
+ "type": "array",
34
+ "description": "The products added to the cart.",
35
+ "minItems": 1,
36
+ "items": {
37
+ "$ref": "./components/product.json"
38
+ }
39
+ }
40
+ },
41
+ "required": ["currency", "items"]
42
+ }
43
+ },
44
+ "required": ["$schema", "event"]
45
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/choice-event.json",
4
+ "title": "Choice Event",
5
+ "description": "An example event that uses oneOf and anyOf.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "description": "Defines the structure of the event. This can be used to validate an event against the schema provided.",
11
+ "const": "events/choice-event.json"
12
+ },
13
+ "event": {
14
+ "type": "string",
15
+ "const": "one_of_event"
16
+ },
17
+ "user_id": {
18
+ "description": "The user's ID.",
19
+ "oneOf": [
20
+ {
21
+ "type": "string",
22
+ "title": "User ID as String",
23
+ "description": "The user's ID as a string.",
24
+ "examples": ["user-123"]
25
+ },
26
+ {
27
+ "type": "integer",
28
+ "title": "User ID as Integer",
29
+ "description": "The user's ID as an integer.",
30
+ "examples": [123]
31
+ }
32
+ ]
33
+ },
34
+ "payment_method": {
35
+ "description": "The user's payment method.",
36
+ "type": "object",
37
+ "anyOf": [
38
+ {
39
+ "title": "Credit Card",
40
+ "type": "object",
41
+ "properties": {
42
+ "payment_type": {
43
+ "type": "string",
44
+ "enum": ["credit_card", "debit_card"],
45
+ "examples": ["credit_card"]
46
+ },
47
+ "card_number": {
48
+ "type": "string",
49
+ "examples": ["1234-5678-9012-3456"]
50
+ },
51
+ "expiry_date": {
52
+ "type": "string",
53
+ "examples": ["12/26"]
54
+ }
55
+ },
56
+ "required": ["card_number", "expiry_date"]
57
+ },
58
+ {
59
+ "title": "PayPal",
60
+ "type": "object",
61
+ "properties": {
62
+ "payment_type": {
63
+ "type": "string",
64
+ "const": "paypal"
65
+ },
66
+ "email": {
67
+ "type": "string",
68
+ "format": "email",
69
+ "examples": ["test@example.com"]
70
+ }
71
+ },
72
+ "required": ["email"]
73
+ }
74
+ ]
75
+ }
76
+ },
77
+ "required": ["event", "user_id", "payment_method"]
78
+ }
@@ -0,0 +1,193 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/complex-event.json",
4
+ "title": "Complex Event with Validation Constraints",
5
+ "description": "A generic event demonstrating various validation constraints and recursive documentation capabilities.",
6
+ "type": "object",
7
+ "required": [
8
+ "$schema",
9
+ "event",
10
+ "number_constraints",
11
+ "string_constraints",
12
+ "user_data"
13
+ ],
14
+ "properties": {
15
+ "$schema": {
16
+ "type": "string",
17
+ "description": "Defines the structure of the event. This can be used to validate an event against the schema provided.",
18
+ "const": "events/complex-event.json"
19
+ },
20
+ "event": {
21
+ "type": "string",
22
+ "const": "user_update",
23
+ "description": "The event name.",
24
+ "examples": ["user_update"]
25
+ },
26
+ "timestamp": {
27
+ "type": "integer",
28
+ "description": "Unix timestamp of the event.",
29
+ "examples": [16788922]
30
+ },
31
+ "user_data": {
32
+ "type": "object",
33
+ "description": "Container for user information.",
34
+ "required": ["user_id", "attributes"],
35
+ "properties": {
36
+ "user_id": {
37
+ "type": "string",
38
+ "description": "Unique User ID.",
39
+ "examples": ["U_999"]
40
+ },
41
+ "is_active": {
42
+ "type": "boolean",
43
+ "description": "Status of the user.",
44
+ "examples": [true]
45
+ },
46
+ "attributes": {
47
+ "type": "object",
48
+ "description": "Nested generic attributes.",
49
+ "properties": {
50
+ "segment": {
51
+ "type": "string",
52
+ "description": "Marketing segment.",
53
+ "examples": ["premium"]
54
+ },
55
+ "score": {
56
+ "type": "number",
57
+ "description": "Engagement score.",
58
+ "examples": [95]
59
+ }
60
+ }
61
+ },
62
+ "addresses": {
63
+ "type": "array",
64
+ "description": "List of user addresses.",
65
+ "items": {
66
+ "type": "object",
67
+ "required": ["city", "zip"],
68
+ "properties": {
69
+ "street": {
70
+ "type": "string",
71
+ "examples": ["123 Main St"]
72
+ },
73
+ "city": {
74
+ "type": "string",
75
+ "examples": ["New York"]
76
+ },
77
+ "zip": {
78
+ "type": "string",
79
+ "examples": ["10001"]
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ },
86
+ "string_constraints": {
87
+ "type": "string",
88
+ "description": "A string with various constraints.",
89
+ "minLength": 2,
90
+ "maxLength": 10,
91
+ "pattern": "^[a-z]+$",
92
+ "format": "hostname",
93
+ "examples": ["example"]
94
+ },
95
+ "number_constraints": {
96
+ "type": "number",
97
+ "description": "A number with various constraints.",
98
+ "minimum": 10,
99
+ "maximum": 100,
100
+ "multipleOf": 5,
101
+ "examples": [50]
102
+ },
103
+ "exclusive_number_constraints": {
104
+ "type": "number",
105
+ "description": "A number with exclusive constraints.",
106
+ "exclusiveMinimum": 10,
107
+ "exclusiveMaximum": 100,
108
+ "examples": [50]
109
+ },
110
+ "array_constraints": {
111
+ "type": "array",
112
+ "description": "An array with various constraints.",
113
+ "minItems": 1,
114
+ "maxItems": 5,
115
+ "uniqueItems": true,
116
+ "items": {
117
+ "type": "string"
118
+ },
119
+ "examples": [["a", "b"]]
120
+ },
121
+ "contains_array_constraints": {
122
+ "type": "array",
123
+ "description": "An array with contains constraints.",
124
+ "contains": {
125
+ "type": "integer"
126
+ },
127
+ "minContains": 1,
128
+ "maxContains": 2,
129
+ "examples": [[1, "text", 2]]
130
+ },
131
+ "object_constraints": {
132
+ "type": "object",
133
+ "description": "An object with various constraints.",
134
+ "minProperties": 1,
135
+ "maxProperties": 3,
136
+ "additionalProperties": false,
137
+ "propertyNames": {
138
+ "pattern": "^[a-z0-9_]+$"
139
+ },
140
+ "properties": {
141
+ "prop_a": {
142
+ "type": "string",
143
+ "examples": ["some_value"]
144
+ },
145
+ "prop_b": {
146
+ "type": "string",
147
+ "examples": ["another_value"]
148
+ }
149
+ },
150
+ "examples": [
151
+ {
152
+ "prop_a": "some_value",
153
+ "prop_b": "another_value"
154
+ }
155
+ ]
156
+ },
157
+ "dependent_required_constraint": {
158
+ "type": "object",
159
+ "description": "An object with dependent required properties.",
160
+ "dependentRequired": {
161
+ "credit_card": ["billing_address"]
162
+ },
163
+ "properties": {
164
+ "credit_card": {
165
+ "type": "number",
166
+ "examples": [1234567890123456]
167
+ },
168
+ "billing_address": {
169
+ "type": "string",
170
+ "examples": ["123 Billing Address, Anytown, USA"]
171
+ }
172
+ },
173
+ "examples": [
174
+ {
175
+ "credit_card": 1234567890123456,
176
+ "billing_address": "123 Billing Address, Anytown, USA"
177
+ }
178
+ ]
179
+ },
180
+ "enum_constraint": {
181
+ "type": "string",
182
+ "description": "A property with an enum constraint.",
183
+ "enum": ["admin", "editor", "viewer"],
184
+ "examples": ["admin"]
185
+ },
186
+ "const_constraint": {
187
+ "type": "string",
188
+ "description": "A property that must have a constant value.",
189
+ "const": "must_be_this",
190
+ "examples": ["must_be_this"]
191
+ }
192
+ }
193
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/components/dataLayer.json",
4
+ "title": "dataLayer",
5
+ "description": "Schema for the object structure pushed to the dataLayer.",
6
+ "type": "object",
7
+ "allOf": [
8
+ {
9
+ "$ref": "#/$defs/strictObject"
10
+ }
11
+ ],
12
+ "properties": {
13
+ "event": {
14
+ "type": "string",
15
+ "description": "The name of the event."
16
+ },
17
+ "ecommerce": {
18
+ "type": "object",
19
+ "description": "Ecommerce related data.",
20
+ "x-gtm-clear": true
21
+ },
22
+ "user_data": {
23
+ "type": "object",
24
+ "description": "User related data.",
25
+ "x-gtm-clear": true
26
+ }
27
+ },
28
+ "required": ["event"],
29
+ "$defs": {
30
+ "strictObject": {
31
+ "type": "object",
32
+ "propertyNames": {
33
+ "maxLength": 40,
34
+ "pattern": "^(\\$schema)|[a-z0-9_]+$"
35
+ },
36
+ "additionalProperties": {
37
+ "anyOf": [
38
+ {
39
+ "$ref": "#/$defs/strictObject"
40
+ },
41
+ {
42
+ "type": "array",
43
+ "items": {
44
+ "$ref": "#/$defs/strictObject"
45
+ }
46
+ },
47
+ {
48
+ "not": {
49
+ "type": "object"
50
+ }
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,126 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/components/product.json",
4
+ "title": "A Product",
5
+ "description": "A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.",
6
+ "type": "object",
7
+ "properties": {
8
+ "item_id": {
9
+ "type": "string",
10
+ "description": "The ID of the item. Either item_id or item_name is required.",
11
+ "examples": ["SKU_12345", "PROD_98765"]
12
+ },
13
+ "item_name": {
14
+ "type": "string",
15
+ "description": "The name of the item. Either item_id or item_name is required.",
16
+ "examples": ["Stan and Friends Tee", "Blue Running Shoes"]
17
+ },
18
+ "affiliation": {
19
+ "type": "string",
20
+ "description": "A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.",
21
+ "examples": ["Google Merchandise Store", "Nike Store"]
22
+ },
23
+ "coupon": {
24
+ "type": "string",
25
+ "description": "The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.",
26
+ "examples": ["SUMMER_FUN", "WELCOME20", "SAVE10"]
27
+ },
28
+ "discount": {
29
+ "type": "number",
30
+ "description": "The monetary value of the discount per unit applied to the item.",
31
+ "examples": [2.22, 5, 10.5]
32
+ },
33
+ "index": {
34
+ "type": "number",
35
+ "description": "The index or position of the item in a list.",
36
+ "examples": [0, 1, 2]
37
+ },
38
+ "item_brand": {
39
+ "type": "string",
40
+ "description": "The brand of the item.",
41
+ "examples": ["Google", "Nike", "Adidas"]
42
+ },
43
+ "item_category": {
44
+ "type": "string",
45
+ "description": "The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.",
46
+ "examples": ["Apparel", "Footwear", "Electronics"]
47
+ },
48
+ "item_category2": {
49
+ "type": "string",
50
+ "description": "The second category hierarchy or additional taxonomy of the item.",
51
+ "examples": ["Adult", "Women", "Men"]
52
+ },
53
+ "item_category3": {
54
+ "type": "string",
55
+ "description": "The third category hierarchy or additional taxonomy of the item.",
56
+ "examples": ["Shirts", "Shoes", "Boots"]
57
+ },
58
+ "item_category4": {
59
+ "type": "string",
60
+ "description": "The fourth category hierarchy or additional taxonomy of the item.",
61
+ "examples": ["Crew", "Running", "Casual"]
62
+ },
63
+ "item_category5": {
64
+ "type": "string",
65
+ "description": "The fifth category hierarchy or additional taxonomy of the item.",
66
+ "examples": ["Short sleeve", "Long distance", "Lightweight"]
67
+ },
68
+ "item_list_id": {
69
+ "type": "string",
70
+ "description": "The ID of the list in which the item was presented to the user. If set, item_list_id at the event level is ignored. If not set, item_list_id at the event level is used if available.",
71
+ "examples": ["related_products", "search_results", "recommendations"]
72
+ },
73
+ "item_list_name": {
74
+ "type": "string",
75
+ "description": "The name of the list in which the item was presented to the user. If set, item_list_name at the event level is ignored. If not set, item_list_name at the event level is used if available.",
76
+ "examples": ["Related Products", "Search Results", "Recommended Items"]
77
+ },
78
+ "item_variant": {
79
+ "type": "string",
80
+ "description": "The item variant or unique code or description for additional item details/options.",
81
+ "examples": ["green", "Blue Size 10", "M-Black"]
82
+ },
83
+ "location_id": {
84
+ "type": "string",
85
+ "description": "The physical location associated with the item, such as the location of a brick-and-mortar store. It is recommended to use the Google Place ID that corresponds to the associated item. A custom location ID can also be used. Note: location_id is only available at the item level.",
86
+ "examples": ["ChIJIQBpAG2ahYAR_6128GcTUEo", "store_123", "location_sf"]
87
+ },
88
+ "price": {
89
+ "type": "number",
90
+ "description": "The price of the item in the specified currency unit. If a discount is applied to the item, set price to the reduced per-unit price and provide the per-unit price discount in the discount parameter.",
91
+ "examples": [10.01, 21.01, 89.99]
92
+ },
93
+ "quantity": {
94
+ "type": "number",
95
+ "description": "The item quantity. If not set, quantity is set to 1.",
96
+ "examples": [1, 2, 3],
97
+ "default": 1
98
+ },
99
+ "promotion_id": {
100
+ "type": "string",
101
+ "description": "The ID of the promotion associated with the item.",
102
+ "examples": ["P_12345", "PROMO_001"]
103
+ },
104
+ "promotion_name": {
105
+ "type": "string",
106
+ "description": "The name of the promotion associated with the item.",
107
+ "examples": ["Summer Sale", "Black Friday", "Flash Deal"]
108
+ },
109
+ "creative_name": {
110
+ "type": "string",
111
+ "description": "The name of the promotion creative.",
112
+ "examples": ["summer_banner2", "holiday_email_v1"]
113
+ },
114
+ "creative_slot": {
115
+ "type": "string",
116
+ "description": "The name of the creative slot associated with the item.",
117
+ "examples": ["featured_app_1", "top_banner", "sidebar"]
118
+ },
119
+ "google_business_vertical": {
120
+ "type": "string",
121
+ "description": "The business vertical for the item (e.g., 'retail').",
122
+ "examples": ["retail", "ecommerce"]
123
+ }
124
+ },
125
+ "required": []
126
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "events/purchase-event.json",
4
+ "title": "Purchase Event",
5
+ "description": "A purchase event fires when a user completes a purchase. Based on Google Analytics 4 ecommerce event specifications.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "description": "Defines the structure of the event. This can be used to validate an event against the schema provided.",
11
+ "const": "events/purchase-event.json"
12
+ },
13
+ "event": {
14
+ "type": "string",
15
+ "const": "purchase",
16
+ "description": "The name of the event indicating a purchase has occurred."
17
+ },
18
+ "ecommerce": {
19
+ "type": "object",
20
+ "description": "Ecommerce related data for the purchase event.",
21
+ "properties": {
22
+ "transaction_id": {
23
+ "type": "string",
24
+ "description": "The unique ID of a transaction. The transaction_id parameter helps avoid duplicate transaction recording.",
25
+ "examples": ["T_12345", "TXN_20231205_001"]
26
+ },
27
+ "value": {
28
+ "type": "number",
29
+ "description": "The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.",
30
+ "examples": [72.05, 99.99, 150.5]
31
+ },
32
+ "currency": {
33
+ "type": "string",
34
+ "description": "The currency of the items in ISO 4217 three-letter format. Required when value is set.",
35
+ "minLength": 3,
36
+ "maxLength": 3,
37
+ "examples": ["USD", "EUR", "GBP"]
38
+ },
39
+ "coupon": {
40
+ "type": "string",
41
+ "description": "The coupon/code associated with the event. Event-level and item-level coupon parameters are independent.",
42
+ "examples": ["SUMMER_SALE", "WELCOME15"]
43
+ },
44
+ "shipping": {
45
+ "type": "number",
46
+ "description": "The shipping cost associated with the transaction.",
47
+ "examples": [5.99, 10, 0]
48
+ },
49
+ "tax": {
50
+ "type": "number",
51
+ "description": "The tax associated with the transaction.",
52
+ "examples": [3.6, 7.5, 0]
53
+ },
54
+ "customer_type": {
55
+ "type": "string",
56
+ "enum": ["new", "returning"],
57
+ "description": "Whether this is from a new or returning customer. 'new' = customer with no purchase in the specified time window (default 540 days). 'returning' = customer with purchase in the specified time window.",
58
+ "examples": ["new", "returning"]
59
+ },
60
+ "items": {
61
+ "type": "array",
62
+ "description": "The products purchased in the transaction.",
63
+ "minItems": 1,
64
+ "items": {
65
+ "$ref": "./components/product.json"
66
+ }
67
+ }
68
+ },
69
+ "required": ["transaction_id", "value", "currency", "items"]
70
+ }
71
+ },
72
+ "required": ["$schema", "event"]
73
+ }