docusaurus-plugin-generate-schema-docs 1.8.3 → 1.8.5

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 (62) hide show
  1. package/README.md +12 -0
  2. package/__tests__/__fixtures__/validateSchemas/main-schema-with-not-allof.json +11 -0
  3. package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof-multi.json +12 -0
  4. package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof.json +30 -0
  5. package/__tests__/__fixtures__/validateSchemas/schema-with-not-edge-cases.json +24 -0
  6. package/__tests__/__fixtures__/validateSchemas/schema-with-not-non-object.json +15 -0
  7. package/__tests__/__snapshots__/generateEventDocs.anchor.test.js.snap +6 -0
  8. package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +6 -0
  9. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +15 -0
  10. package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +6 -0
  11. package/__tests__/components/PropertiesTable.test.js +66 -0
  12. package/__tests__/components/PropertyRow.test.js +85 -4
  13. package/__tests__/components/SchemaJsonViewer.test.js +118 -0
  14. package/__tests__/generateEventDocs.anchor.test.js +1 -1
  15. package/__tests__/generateEventDocs.nested.test.js +1 -1
  16. package/__tests__/generateEventDocs.partials.test.js +1 -1
  17. package/__tests__/generateEventDocs.test.js +506 -1
  18. package/__tests__/generateEventDocs.versioned.test.js +1 -1
  19. package/__tests__/helpers/buildExampleFromSchema.test.js +240 -0
  20. package/__tests__/helpers/constraintSchemaPaths.test.js +208 -0
  21. package/__tests__/helpers/continuingLinesStyle.test.js +492 -0
  22. package/__tests__/helpers/example-helper.test.js +12 -0
  23. package/__tests__/helpers/exampleModel.test.js +209 -0
  24. package/__tests__/helpers/file-system.test.js +73 -1
  25. package/__tests__/helpers/getConstraints.test.js +43 -0
  26. package/__tests__/helpers/mergeSchema.test.js +94 -0
  27. package/__tests__/helpers/processSchema.test.js +309 -1
  28. package/__tests__/helpers/schema-doc-template.test.js +54 -0
  29. package/__tests__/helpers/schema-processing.test.js +122 -2
  30. package/__tests__/helpers/schemaToExamples.test.js +1007 -0
  31. package/__tests__/helpers/schemaToTableData.mutations.test.js +970 -0
  32. package/__tests__/helpers/schemaToTableData.test.js +157 -0
  33. package/__tests__/helpers/schemaTraversal.test.js +110 -0
  34. package/__tests__/helpers/snippetTargets.test.js +432 -0
  35. package/__tests__/helpers/trackingTargets.test.js +319 -0
  36. package/__tests__/helpers/validator.test.js +385 -1
  37. package/__tests__/index.test.js +436 -0
  38. package/__tests__/syncGtm.test.js +366 -6
  39. package/__tests__/update-schema-ids.test.js +70 -1
  40. package/__tests__/validateSchemas-integration.test.js +2 -2
  41. package/__tests__/validateSchemas.test.js +192 -1
  42. package/components/PropertiesTable.js +32 -2
  43. package/components/PropertyRow.js +29 -2
  44. package/components/SchemaJsonViewer.js +234 -131
  45. package/components/SchemaRows.css +40 -0
  46. package/components/SchemaViewer.js +11 -2
  47. package/generateEventDocs.js +21 -1
  48. package/helpers/constraintSchemaPaths.js +10 -14
  49. package/helpers/example-helper.js +2 -2
  50. package/helpers/getConstraints.js +20 -0
  51. package/helpers/processSchema.js +32 -1
  52. package/helpers/schema-doc-template.js +4 -0
  53. package/helpers/schemaToExamples.js +29 -35
  54. package/helpers/schemaToTableData.js +538 -492
  55. package/helpers/schemaTraversal.cjs +148 -0
  56. package/helpers/trackingTargets.js +26 -3
  57. package/helpers/validator.js +18 -4
  58. package/index.js +1 -2
  59. package/package.json +1 -1
  60. package/scripts/sync-gtm.js +65 -34
  61. package/test-data/payloadContracts.js +35 -0
  62. package/validateSchemas.js +1 -1
package/README.md CHANGED
@@ -90,6 +90,8 @@ docusaurus sync-gtm
90
90
 
91
91
  By default, it resolves schemas from the project root. Use `--path=<siteDir>` to target a different site directory.
92
92
 
93
+ Only schemas tagged with `x-tracking-targets` including `web-datalayer-js` are used for GTM variable sync. Untagged schemas are ignored.
94
+
93
95
  ### Firebase Snippet Targets
94
96
 
95
97
  `ExampleDataLayer` supports Firebase snippet targets for:
@@ -201,6 +203,16 @@ If you have `event-reference/add-to-cart-event` and `mobile-reference/add-to-car
201
203
  - `docs/partials/event-reference/_add-to-cart-event.mdx`
202
204
  - `docs/partials/event-reference/_add-to-cart-event_bottom.mdx`
203
205
 
206
+ ## Related packages
207
+
208
+ ### [`eslint-plugin-tracking-schema`](https://www.npmjs.com/package/eslint-plugin-tracking-schema)
209
+
210
+ An ESLint plugin that enforces annotation quality on the JSON Schema files you feed into this plugin. It ensures every property has a `description`, a `type`, and `examples` — catching incomplete schemas at author time before they produce misleading documentation.
211
+
212
+ ```bash
213
+ npm install --save-dev eslint-plugin-tracking-schema jsonc-eslint-parser
214
+ ```
215
+
204
216
  ## Contributing
205
217
 
206
218
  Contributions are welcome! Please open an issue or submit a pull request if you have any ideas or improvements.
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://example.com/main-schema-with-not-allof.json",
4
+ "title": "Main Schema With Not AllOf",
5
+ "type": "object",
6
+ "properties": {
7
+ "country": {
8
+ "allOf": [{ "type": "string" }, { "not": { "const": "US" } }]
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://example.com/schema-with-not-anyof-multi.json",
4
+ "title": "Schema With Not AnyOf Multi",
5
+ "type": "object",
6
+ "properties": {
7
+ "country": {
8
+ "type": "string",
9
+ "not": { "anyOf": [{ "const": "US" }, { "const": "CA" }] }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://example.com/schema-with-not-anyof.json",
4
+ "title": "Schema With Not AnyOf",
5
+ "type": "object",
6
+ "properties": {
7
+ "country": {
8
+ "type": "string",
9
+ "not": { "anyOf": [{ "const": "US" }] }
10
+ },
11
+ "nested": {
12
+ "type": "object",
13
+ "properties": {
14
+ "code": {
15
+ "type": "string",
16
+ "not": { "anyOf": [{ "anyOf": [{ "const": "XX" }] }] }
17
+ }
18
+ }
19
+ },
20
+ "items": {
21
+ "type": "array",
22
+ "items": [
23
+ {
24
+ "type": "string",
25
+ "not": { "anyOf": [{ "const": "forbidden" }] }
26
+ }
27
+ ]
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://example.com/schema-with-not-edge-cases.json",
4
+ "title": "Schema With Not Edge Cases",
5
+ "type": "object",
6
+ "properties": {
7
+ "falsy_not": {
8
+ "type": "string",
9
+ "not": false
10
+ },
11
+ "not_is_array": {
12
+ "type": "string",
13
+ "not": [{ "const": "A" }, { "const": "B" }]
14
+ },
15
+ "not_anyof_contains_array": {
16
+ "type": "string",
17
+ "not": { "anyOf": [[1, 2, 3]] }
18
+ },
19
+ "not_with_null_candidate": {
20
+ "type": "string",
21
+ "not": { "anyOf": [null] }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://example.com/schema-with-not-non-object.json",
4
+ "title": "Schema With Not Non Object",
5
+ "type": "object",
6
+ "properties": {
7
+ "flag": {
8
+ "not": true
9
+ },
10
+ "name": {
11
+ "type": "string",
12
+ "not": { "const": "forbidden" }
13
+ }
14
+ }
15
+ }
@@ -46,6 +46,9 @@ This is a child event with an anchor.
46
46
 
47
47
  <SchemaViewer
48
48
  schema={{"$id":"https://example.com/parent-event-anchor.json#child-event-with-anchor","title":"Child Event Anchor","description":"This is a child event with an anchor.","type":"object","$anchor":"child-event-with-anchor","properties":{"property_a":{"type":"string"}}}}
49
+ sourceSchema={{"$id":"https://example.com/parent-event-anchor.json","title":"Parent Event Anchor","description":"This is a parent event with oneOf.","type":"object","oneOf":[{"title":"Child Event Anchor","description":"This is a child event with an anchor.","$anchor":"child-event-with-anchor","type":"object","properties":{"property_a":{"type":"string"}}},{"title":"Child Event Title","description":"This is a child event with only a title.","type":"object","properties":{"property_b":{"type":"string"}}}]}}
50
+ sourcePath={"parent-event-anchor.json"}
51
+ schemaSources={{"parent-event-anchor.json":{"$id":"https://example.com/parent-event-anchor.json","title":"Parent Event Anchor","description":"This is a parent event with oneOf.","type":"object","oneOf":[{"title":"Child Event Anchor","description":"This is a child event with an anchor.","$anchor":"child-event-with-anchor","type":"object","properties":{"property_a":{"type":"string"}}},{"title":"Child Event Title","description":"This is a child event with only a title.","type":"object","properties":{"property_b":{"type":"string"}}}]}}}
49
52
 
50
53
  />
51
54
  <SchemaJsonViewer
@@ -79,6 +82,9 @@ This is a child event with only a title.
79
82
 
80
83
  <SchemaViewer
81
84
  schema={{"$id":"https://example.com/parent-event-anchor.json#child-event-title","title":"Child Event Title","description":"This is a child event with only a title.","type":"object","properties":{"property_b":{"type":"string"}}}}
85
+ sourceSchema={{"$id":"https://example.com/parent-event-anchor.json","title":"Parent Event Anchor","description":"This is a parent event with oneOf.","type":"object","oneOf":[{"title":"Child Event Anchor","description":"This is a child event with an anchor.","$anchor":"child-event-with-anchor","type":"object","properties":{"property_a":{"type":"string"}}},{"title":"Child Event Title","description":"This is a child event with only a title.","type":"object","properties":{"property_b":{"type":"string"}}}]}}
86
+ sourcePath={"parent-event-anchor.json"}
87
+ schemaSources={{"parent-event-anchor.json":{"$id":"https://example.com/parent-event-anchor.json","title":"Parent Event Anchor","description":"This is a parent event with oneOf.","type":"object","oneOf":[{"title":"Child Event Anchor","description":"This is a child event with an anchor.","$anchor":"child-event-with-anchor","type":"object","properties":{"property_a":{"type":"string"}}},{"title":"Child Event Title","description":"This is a child event with only a title.","type":"object","properties":{"property_b":{"type":"string"}}}]}}}
82
88
 
83
89
  />
84
90
  <SchemaJsonViewer
@@ -70,6 +70,9 @@ undefined
70
70
 
71
71
  <SchemaViewer
72
72
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-a.json","title":"Grandchild A","type":"object","properties":{"prop_a":{"type":"string"}}}}
73
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/child-event.json","title":"Child Event","type":"object","oneOf":[{"$ref":"./grandchild-a.json"},{"$ref":"./grandchild-b.json"}]}}
74
+ sourcePath={"child-event.json"}
75
+ schemaSources={{"child-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/child-event.json","title":"Child Event","type":"object","oneOf":[{"$ref":"./grandchild-a.json"},{"$ref":"./grandchild-b.json"}]},"grandchild-a.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-a.json","title":"Grandchild A","type":"object","properties":{"prop_a":{"type":"string"}}},"grandchild-b.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-b.json","title":"Grandchild B","type":"object","properties":{"prop_b":{"type":"string"}}}}}
73
76
 
74
77
  />
75
78
  <SchemaJsonViewer
@@ -103,6 +106,9 @@ undefined
103
106
 
104
107
  <SchemaViewer
105
108
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-b.json","title":"Grandchild B","type":"object","properties":{"prop_b":{"type":"string"}}}}
109
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/child-event.json","title":"Child Event","type":"object","oneOf":[{"$ref":"./grandchild-a.json"},{"$ref":"./grandchild-b.json"}]}}
110
+ sourcePath={"child-event.json"}
111
+ schemaSources={{"child-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/child-event.json","title":"Child Event","type":"object","oneOf":[{"$ref":"./grandchild-a.json"},{"$ref":"./grandchild-b.json"}]},"grandchild-a.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-a.json","title":"Grandchild A","type":"object","properties":{"prop_a":{"type":"string"}}},"grandchild-b.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/schemas/nested/grandchild-b.json","title":"Grandchild B","type":"object","properties":{"prop_b":{"type":"string"}}}}}
106
112
 
107
113
  />
108
114
  <SchemaJsonViewer
@@ -21,6 +21,9 @@ An add_to_cart event fires when a user adds one or more items to their shopping
21
21
 
22
22
  <SchemaViewer
23
23
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/allOf/0/$defs/strictObject"},{"type":"array","items":{"$ref":"#/allOf/0/$defs/strictObject"}},{"not":{"type":"object"}}]}}},"$ref":"#/allOf/0/$defs/strictObject","properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","required":["currency","items"],"x-gtm-clear":true,"properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","required":[],"properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}}}}}},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}}}}
24
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}}}
25
+ sourcePath={"add-to-cart-event.json"}
26
+ schemaSources={{"add-to-cart-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}},"components/dataLayer.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/dataLayer.json","title":"dataLayer","description":"Schema for the object structure pushed to the dataLayer.","type":"object","allOf":[{"$ref":"#/$defs/strictObject"}],"properties":{"event":{"type":"string","description":"The name of the event."},"ecommerce":{"type":"object","description":"Ecommerce related data.","x-gtm-clear":true},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}},"required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/$defs/strictObject"},{"type":"array","items":{"$ref":"#/$defs/strictObject"}},{"not":{"type":"object"}}]}}}},"components/product.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}},"required":[]}}}
24
27
 
25
28
  />
26
29
  <SchemaJsonViewer
@@ -54,6 +57,9 @@ An example event that uses oneOf and anyOf.
54
57
 
55
58
  <SchemaViewer
56
59
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/choice-event.json","title":"Choice Event","description":"An example event that uses oneOf and anyOf.","type":"object","required":["event","user_id","payment_method"],"properties":{"event":{"type":"string","const":"one_of_event"},"user_id":{"description":"The user's ID.","oneOf":[{"type":"string","title":"User ID as String","description":"The user's ID as a string.","examples":["user-123"]},{"type":"integer","title":"User ID as Integer","description":"The user's ID as an integer.","examples":[123]}]},"payment_method":{"description":"The user's payment method.","type":"object","anyOf":[{"title":"Credit Card","properties":{"payment_type":{"type":"string","enum":["credit_card","debit_card"],"examples":["credit_card"]},"card_number":{"type":"string","examples":["1234-5678-9012-3456"]},"expiry_date":{"type":"string","examples":["12/26"]}},"required":["card_number","expiry_date"]},{"title":"PayPal","type":"object","properties":{"payment_type":{"type":"string","const":"paypal"},"email":{"type":"string","format":"email","examples":["test@example.com"]}},"required":["email"]}]}}}}
60
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/choice-event.json","title":"Choice Event","description":"An example event that uses oneOf and anyOf.","type":"object","properties":{"event":{"type":"string","const":"one_of_event"},"user_id":{"description":"The user's ID.","oneOf":[{"type":"string","title":"User ID as String","description":"The user's ID as a string.","examples":["user-123"]},{"type":"integer","title":"User ID as Integer","description":"The user's ID as an integer.","examples":[123]}]},"payment_method":{"description":"The user's payment method.","type":"object","anyOf":[{"title":"Credit Card","properties":{"payment_type":{"type":"string","enum":["credit_card","debit_card"],"examples":["credit_card"]},"card_number":{"type":"string","examples":["1234-5678-9012-3456"]},"expiry_date":{"type":"string","examples":["12/26"]}},"required":["card_number","expiry_date"]},{"title":"PayPal","type":"object","properties":{"payment_type":{"type":"string","const":"paypal"},"email":{"type":"string","format":"email","examples":["test@example.com"]}},"required":["email"]}]}},"required":["event","user_id","payment_method"]}}
61
+ sourcePath={"choice-event.json"}
62
+ schemaSources={{"choice-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/choice-event.json","title":"Choice Event","description":"An example event that uses oneOf and anyOf.","type":"object","properties":{"event":{"type":"string","const":"one_of_event"},"user_id":{"description":"The user's ID.","oneOf":[{"type":"string","title":"User ID as String","description":"The user's ID as a string.","examples":["user-123"]},{"type":"integer","title":"User ID as Integer","description":"The user's ID as an integer.","examples":[123]}]},"payment_method":{"description":"The user's payment method.","type":"object","anyOf":[{"title":"Credit Card","properties":{"payment_type":{"type":"string","enum":["credit_card","debit_card"],"examples":["credit_card"]},"card_number":{"type":"string","examples":["1234-5678-9012-3456"]},"expiry_date":{"type":"string","examples":["12/26"]}},"required":["card_number","expiry_date"]},{"title":"PayPal","type":"object","properties":{"payment_type":{"type":"string","const":"paypal"},"email":{"type":"string","format":"email","examples":["test@example.com"]}},"required":["email"]}]}},"required":["event","user_id","payment_method"]}}}
57
63
 
58
64
  />
59
65
  <SchemaJsonViewer
@@ -87,6 +93,9 @@ An example event that has anyOf at the root level.
87
93
 
88
94
  <SchemaViewer
89
95
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/root-any-of-event.json","title":"Root AnyOf Event","description":"An example event that has anyOf at the root level.","type":"object","anyOf":[{"title":"Has Param C","properties":{"param_c":{"type":"string","examples":["example_c"],"description":"This is the description for Param C."}}},{"title":"Has Param D","properties":{"param_d":{"type":"boolean","examples":[true]}}}],"properties":{"event":{"type":"string","const":"any_of_event"}}}}
96
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/root-any-of-event.json","title":"Root AnyOf Event","description":"An example event that has anyOf at the root level.","type":"object","properties":{"event":{"type":"string","const":"any_of_event"}},"anyOf":[{"title":"Has Param C","properties":{"param_c":{"type":"string","examples":["example_c"],"description":"This is the description for Param C."}}},{"title":"Has Param D","properties":{"param_d":{"type":"boolean","examples":[true]}}}]}}
97
+ sourcePath={"root-any-of-event.json"}
98
+ schemaSources={{"root-any-of-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/1.2.0/root-any-of-event.json","title":"Root AnyOf Event","description":"An example event that has anyOf at the root level.","type":"object","properties":{"event":{"type":"string","const":"any_of_event"}},"anyOf":[{"title":"Has Param C","properties":{"param_c":{"type":"string","examples":["example_c"],"description":"This is the description for Param C."}}},{"title":"Has Param D","properties":{"param_d":{"type":"boolean","examples":[true]}}}]}}}
90
99
 
91
100
  />
92
101
  <SchemaJsonViewer
@@ -145,6 +154,9 @@ An example event that has oneOf at the root level.
145
154
 
146
155
  <SchemaViewer
147
156
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json#option-a","title":"Option A","description":"An example event that has oneOf at the root level.","type":"object","properties":{"event":{"type":"string","const":"option_a"},"param_a":{"type":"string","examples":["example_a"]}}}}
157
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json","title":"Root Choice Event","description":"An example event that has oneOf at the root level.","oneOf":[{"title":"Option A","type":"object","properties":{"event":{"type":"string","const":"option_a"},"param_a":{"type":"string","examples":["example_a"]}}},{"title":"Option B","type":"object","properties":{"event":{"type":"string","const":"option_b"},"param_b":{"type":"integer","examples":[123]}}}]}}
158
+ sourcePath={"root-choice-event.json"}
159
+ schemaSources={{"root-choice-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json","title":"Root Choice Event","description":"An example event that has oneOf at the root level.","oneOf":[{"title":"Option A","type":"object","properties":{"event":{"type":"string","const":"option_a"},"param_a":{"type":"string","examples":["example_a"]}}},{"title":"Option B","type":"object","properties":{"event":{"type":"string","const":"option_b"},"param_b":{"type":"integer","examples":[123]}}}]}}}
148
160
 
149
161
  />
150
162
  <SchemaJsonViewer
@@ -178,6 +190,9 @@ An example event that has oneOf at the root level.
178
190
 
179
191
  <SchemaViewer
180
192
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json#option-b","title":"Option B","description":"An example event that has oneOf at the root level.","type":"object","properties":{"event":{"type":"string","const":"option_b"},"param_b":{"type":"integer","examples":[123]}}}}
193
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json","title":"Root Choice Event","description":"An example event that has oneOf at the root level.","oneOf":[{"title":"Option A","type":"object","properties":{"event":{"type":"string","const":"option_a"},"param_a":{"type":"string","examples":["example_a"]}}},{"title":"Option B","type":"object","properties":{"event":{"type":"string","const":"option_b"},"param_b":{"type":"integer","examples":[123]}}}]}}
194
+ sourcePath={"root-choice-event.json"}
195
+ schemaSources={{"root-choice-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/root-choice-event.schema.json","title":"Root Choice Event","description":"An example event that has oneOf at the root level.","oneOf":[{"title":"Option A","type":"object","properties":{"event":{"type":"string","const":"option_a"},"param_a":{"type":"string","examples":["example_a"]}}},{"title":"Option B","type":"object","properties":{"event":{"type":"string","const":"option_b"},"param_b":{"type":"integer","examples":[123]}}}]}}}
181
196
 
182
197
  />
183
198
  <SchemaJsonViewer
@@ -21,6 +21,9 @@ An add_to_cart event fires when a user adds one or more items to their shopping
21
21
 
22
22
  <SchemaViewer
23
23
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/allOf/0/$defs/strictObject"},{"type":"array","items":{"$ref":"#/allOf/0/$defs/strictObject"}},{"not":{"type":"object"}}]}}},"$ref":"#/allOf/0/$defs/strictObject","properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","required":["currency","items"],"x-gtm-clear":true,"properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","required":[],"properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}}}}}},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}}}}
24
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}}}
25
+ sourcePath={"add-to-cart-event.json"}
26
+ schemaSources={{"add-to-cart-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}},"components/dataLayer.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/dataLayer.json","title":"dataLayer","description":"Schema for the object structure pushed to the dataLayer.","type":"object","allOf":[{"$ref":"#/$defs/strictObject"}],"properties":{"event":{"type":"string","description":"The name of the event."},"ecommerce":{"type":"object","description":"Ecommerce related data.","x-gtm-clear":true},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}},"required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/$defs/strictObject"},{"type":"array","items":{"$ref":"#/$defs/strictObject"}},{"not":{"type":"object"}}]}}}},"components/product.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}},"required":[]}}}
24
27
 
25
28
  />
26
29
  <SchemaJsonViewer
@@ -54,6 +57,9 @@ An add_to_cart event fires when a user adds one or more items to their shopping
54
57
 
55
58
  <SchemaViewer
56
59
  schema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/allOf/0/$defs/strictObject"},{"type":"array","items":{"$ref":"#/allOf/0/$defs/strictObject"}},{"not":{"type":"object"}}]}}},"$ref":"#/allOf/0/$defs/strictObject","properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","required":["currency","items"],"x-gtm-clear":true,"properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","required":[],"properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}}}}}},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}}}}
60
+ sourceSchema={{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}}}
61
+ sourcePath={"add-to-cart-event.json"}
62
+ schemaSources={{"add-to-cart-event.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/add-to-cart-event.json","title":"Add to Cart Event","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.","type":"object","allOf":[{"$ref":"./components/dataLayer.json"}],"properties":{"event":{"type":"string","const":"add_to_cart","description":"The name of the event indicating a add_to_cart has occurred."},"ecommerce":{"type":"object","description":"Ecommerce related data for the purchase event.","properties":{"value":{"type":"number","description":"The monetary value of the event. Set value to the sum of (price * quantity) for all items in items.","examples":[30.03,99.99,45.5]},"currency":{"type":"string","description":"The currency of the items in ISO 4217 three-letter format. Required when value is set.","examples":["USD","EUR","GBP"]},"items":{"type":"array","description":"The products added to the cart.","minItems":1,"items":{"$ref":"./components/product.json"}}},"required":["currency","items"]}}},"components/dataLayer.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/dataLayer.json","title":"dataLayer","description":"Schema for the object structure pushed to the dataLayer.","type":"object","allOf":[{"$ref":"#/$defs/strictObject"}],"properties":{"event":{"type":"string","description":"The name of the event."},"ecommerce":{"type":"object","description":"Ecommerce related data.","x-gtm-clear":true},"user_data":{"type":"object","description":"User related data.","x-gtm-clear":true}},"required":["event"],"$defs":{"strictObject":{"type":"object","propertyNames":{"maxLength":40,"pattern":"^[a-z0-9_]+$"},"additionalProperties":{"anyOf":[{"$ref":"#/$defs/strictObject"},{"type":"array","items":{"$ref":"#/$defs/strictObject"}},{"not":{"type":"object"}}]}}}},"components/product.json":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://tracking-docs-demo.buchert.digital/schemas/components/product.json","title":"A Product","description":"A product object representing an item for use within a purchase event, based on Google Analytics 4 ecommerce event specifications.","type":"object","properties":{"item_id":{"type":"string","description":"The ID of the item. Either item_id or item_name is required.","examples":["SKU_12345","PROD_98765"]},"item_name":{"type":"string","description":"The name of the item. Either item_id or item_name is required.","examples":["Stan and Friends Tee","Blue Running Shoes"]},"affiliation":{"type":"string","description":"A product affiliation to indicate a supplier or store. Note: affiliation is only available at the item level.","examples":["Google Merchandise Store","Nike Store"]},"coupon":{"type":"string","description":"The coupon name/code associated with the item. Coupon parameters at event and item levels are independent.","examples":["SUMMER_FUN","WELCOME20","SAVE10"]},"discount":{"type":"number","description":"The monetary value of the discount per unit applied to the item.","examples":[2.22,5,10.5]},"index":{"type":"number","description":"The index or position of the item in a list.","examples":[0,1,2]},"item_brand":{"type":"string","description":"The brand of the item.","examples":["Google","Nike","Adidas"]},"item_category":{"type":"string","description":"The category of the item. If used as part of a category hierarchy or taxonomy, this is the first category.","examples":["Apparel","Footwear","Electronics"]},"item_category2":{"type":"string","description":"The second category hierarchy or additional taxonomy of the item.","examples":["Adult","Women","Men"]},"item_category3":{"type":"string","description":"The third category hierarchy or additional taxonomy of the item.","examples":["Shirts","Shoes","Boots"]},"item_category4":{"type":"string","description":"The fourth category hierarchy or additional taxonomy of the item.","examples":["Crew","Running","Casual"]},"item_category5":{"type":"string","description":"The fifth category hierarchy or additional taxonomy of the item.","examples":["Short sleeve","Long distance","Lightweight"]},"item_list_id":{"type":"string","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.","examples":["related_products","search_results","recommendations"]},"item_list_name":{"type":"string","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.","examples":["Related Products","Search Results","Recommended Items"]},"item_variant":{"type":"string","description":"The item variant or unique code or description for additional item details/options.","examples":["green","Blue Size 10","M-Black"]},"location_id":{"type":"string","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.","examples":["ChIJIQBpAG2ahYAR_6128GcTUEo","store_123","location_sf"]},"price":{"type":"number","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.","examples":[10.01,21.01,89.99]},"quantity":{"type":"number","description":"The item quantity. If not set, quantity is set to 1.","examples":[1,2,3]},"promotion_id":{"type":"string","description":"The ID of the promotion associated with the item.","examples":["P_12345","PROMO_001"]},"promotion_name":{"type":"string","description":"The name of the promotion associated with the item.","examples":["Summer Sale","Black Friday","Flash Deal"]},"creative_name":{"type":"string","description":"The name of the promotion creative.","examples":["summer_banner2","holiday_email_v1"]},"creative_slot":{"type":"string","description":"The name of the creative slot associated with the item.","examples":["featured_app_1","top_banner","sidebar"]},"google_business_vertical":{"type":"string","description":"The business vertical for the item (e.g., 'retail').","examples":["retail","ecommerce"]}},"required":[]}}}
57
63
 
58
64
  />
59
65
  <SchemaJsonViewer
@@ -2,6 +2,11 @@ import '@testing-library/jest-dom';
2
2
  import React from 'react';
3
3
  import { render, fireEvent } from '@testing-library/react';
4
4
  import PropertiesTable from '../../components/PropertiesTable';
5
+ import { schemaToTableData } from '../../helpers/schemaToTableData';
6
+
7
+ jest.mock('../../helpers/schemaToTableData', () => ({
8
+ schemaToTableData: jest.fn(() => []),
9
+ }));
5
10
 
6
11
  jest.mock('../../components/TableHeader', () => {
7
12
  const MockTableHeader = () => (
@@ -32,6 +37,10 @@ jest.mock('../../components/WordWrapButton', () => {
32
37
  });
33
38
 
34
39
  describe('PropertiesTable', () => {
40
+ beforeEach(() => {
41
+ schemaToTableData.mockClear();
42
+ });
43
+
35
44
  it('renders the table with header and schema rows', () => {
36
45
  const schema = {
37
46
  properties: {
@@ -46,6 +55,63 @@ describe('PropertiesTable', () => {
46
55
  expect(getByText('Mocked SchemaRows')).toBeInTheDocument();
47
56
  });
48
57
 
58
+ it('filters out inherited top-level properties without description or examples', () => {
59
+ const schema = {
60
+ properties: {
61
+ event: { type: 'string' },
62
+ items: { type: 'array' },
63
+ },
64
+ required: ['event'],
65
+ };
66
+ const sourceSchema = {
67
+ properties: {
68
+ event: { type: 'string' },
69
+ },
70
+ };
71
+
72
+ render(<PropertiesTable schema={schema} sourceSchema={sourceSchema} />);
73
+
74
+ expect(schemaToTableData).toHaveBeenCalledWith({
75
+ ...schema,
76
+ properties: {
77
+ event: { type: 'string' },
78
+ },
79
+ });
80
+ });
81
+
82
+ it('keeps inherited top-level properties when they include documentation fields', () => {
83
+ const schema = {
84
+ properties: {
85
+ event: { type: 'string' },
86
+ app_version: {
87
+ type: 'string',
88
+ description: 'Shared app version for all mobile events.',
89
+ examples: ['1.2.3'],
90
+ },
91
+ },
92
+ required: ['event'],
93
+ };
94
+ const sourceSchema = {
95
+ properties: {
96
+ event: { type: 'string' },
97
+ },
98
+ };
99
+
100
+ render(<PropertiesTable schema={schema} sourceSchema={sourceSchema} />);
101
+
102
+ expect(schemaToTableData).toHaveBeenCalledWith({
103
+ ...schema,
104
+ properties: {
105
+ event: { type: 'string' },
106
+ app_version: {
107
+ type: 'string',
108
+ description: 'Shared app version for all mobile events.',
109
+ examples: ['1.2.3'],
110
+ },
111
+ },
112
+ });
113
+ });
114
+
49
115
  it('toggles word wrap when the button is clicked', () => {
50
116
  const schema = {
51
117
  properties: {
@@ -56,6 +56,31 @@ describe('PropertyRow', () => {
56
56
  expect(getByText('"John Doe"')).toBeInTheDocument();
57
57
  });
58
58
 
59
+ it('renders array type values as comma-separated text', () => {
60
+ const row = {
61
+ name: 'additionalProperties',
62
+ level: 0,
63
+ required: false,
64
+ propertyType: ['string', 'number', 'integer', 'boolean', 'null'],
65
+ description: 'Catch-all values.',
66
+ examples: [],
67
+ constraints: [],
68
+ path: ['additionalProperties'],
69
+ };
70
+
71
+ const { getByText } = render(
72
+ <table>
73
+ <tbody>
74
+ <PropertyRow row={row} />
75
+ </tbody>
76
+ </table>,
77
+ );
78
+
79
+ expect(
80
+ getByText('string, number, integer, boolean, null'),
81
+ ).toBeInTheDocument();
82
+ });
83
+
59
84
  it('marks required properties', () => {
60
85
  const row = {
61
86
  name: 'name',
@@ -247,16 +272,22 @@ describe('PropertyRow', () => {
247
272
  expect(
248
273
  container.querySelector('.property-name--keyword'),
249
274
  ).toBeInTheDocument();
275
+ expect(
276
+ container.querySelector('.property-keyword-badge'),
277
+ ).toBeInTheDocument();
278
+ expect(getByText('Schema constraint')).toBeInTheDocument();
250
279
  expect(keyword).not.toHaveAttribute('title');
251
280
  expect(keyword).toHaveAttribute(
252
281
  'aria-describedby',
253
- 'schema-keyword-help-additionalProperties',
282
+ 'schema-keyword-help-user_properties-additionalProperties',
254
283
  );
255
284
  expect(
256
285
  container.querySelector('.property-keyword-tooltip'),
257
286
  ).toBeInTheDocument();
258
287
  expect(
259
- container.querySelector('#schema-keyword-help-additionalProperties'),
288
+ container.querySelector(
289
+ '#schema-keyword-help-user_properties-additionalProperties',
290
+ ),
260
291
  ).toBeInTheDocument();
261
292
  expect(
262
293
  getByText(
@@ -266,6 +297,14 @@ describe('PropertyRow', () => {
266
297
  expect(container.querySelector('.is-last')).toBeInTheDocument();
267
298
  });
268
299
 
300
+ it('defines keyword badge styles in CSS', () => {
301
+ const cssPath = path.join(__dirname, '../../components/SchemaRows.css');
302
+ const css = fs.readFileSync(cssPath, 'utf8');
303
+
304
+ expect(css).toContain('.property-keyword-badge');
305
+ expect(css).toContain('text-transform: uppercase');
306
+ });
307
+
269
308
  it('renders patternProperties rows as schema keywords with tooltip help', () => {
270
309
  const row = {
271
310
  name: 'patternProperties /^custom_/',
@@ -298,11 +337,11 @@ describe('PropertyRow', () => {
298
337
  ).toBeInTheDocument();
299
338
  expect(keyword).toHaveAttribute(
300
339
  'aria-describedby',
301
- 'schema-keyword-help-patternProperties /^custom_/',
340
+ 'schema-keyword-help-attributes-patternProperties___custom__',
302
341
  );
303
342
  expect(
304
343
  container.ownerDocument.getElementById(
305
- 'schema-keyword-help-patternProperties /^custom_/',
344
+ 'schema-keyword-help-attributes-patternProperties___custom__',
306
345
  ),
307
346
  ).toBeInTheDocument();
308
347
  expect(
@@ -313,6 +352,48 @@ describe('PropertyRow', () => {
313
352
  expect(container.querySelector('.is-last')).toBeInTheDocument();
314
353
  });
315
354
 
355
+ it('uses unique tooltip ids for repeated schema keyword rows', () => {
356
+ const firstRow = {
357
+ name: 'additionalProperties',
358
+ level: 1,
359
+ required: false,
360
+ propertyType: 'string',
361
+ description: 'User property values.',
362
+ examples: ['beta_tester'],
363
+ constraints: [],
364
+ path: ['user_properties', 'additionalProperties'],
365
+ hasChildren: false,
366
+ containerType: null,
367
+ continuingLevels: [],
368
+ isSchemaKeywordRow: true,
369
+ keepConnectorOpen: false,
370
+ };
371
+ const secondRow = {
372
+ ...firstRow,
373
+ path: ['metadata', 'additionalProperties'],
374
+ description: 'Metadata values.',
375
+ };
376
+
377
+ const { container, getAllByText } = render(
378
+ <table>
379
+ <tbody>
380
+ <PropertyRow row={firstRow} isLastInGroup={true} />
381
+ <PropertyRow row={secondRow} isLastInGroup={true} />
382
+ </tbody>
383
+ </table>,
384
+ );
385
+
386
+ const keywords = getAllByText('additionalProperties');
387
+ const firstTooltipId = keywords[0].getAttribute('aria-describedby');
388
+ const secondTooltipId = keywords[1].getAttribute('aria-describedby');
389
+
390
+ expect(firstTooltipId).toBeTruthy();
391
+ expect(secondTooltipId).toBeTruthy();
392
+ expect(firstTooltipId).not.toBe(secondTooltipId);
393
+ expect(container.querySelector(`#${firstTooltipId}`)).toBeInTheDocument();
394
+ expect(container.querySelector(`#${secondTooltipId}`)).toBeInTheDocument();
395
+ });
396
+
316
397
  describe('hierarchical lines feature', () => {
317
398
  it('renders {} symbol for object containers', () => {
318
399
  const row = {