From d38619103e01d229d686f13f19aeebbcc228d6e3 Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Wed, 4 Oct 2023 17:01:45 +0200 Subject: [PATCH] feat(specs): add new events type for insights (#2080) Co-authored-by: Jessica --- .../codegen/cts/AlgoliaCTSGenerator.java | 1 + .../cts/lambda/EscapeDollarLambda.java | 15 +++++ .../codegen/cts/tests/TestsRequest.java | 10 +++ specs/insights/common/enums.yml | 3 - .../common/schemas/AddToCartEvent.yml | 2 + .../common/schemas/AddedToCartObjectIDs.yml | 33 +++++++++ .../AddedToCartObjectIDsAfterSearch.yml | 35 ++++++++++ .../common/schemas/EventAttributes.yml | 66 ++++++++++++++++++ specs/insights/common/schemas/EventsItems.yml | 4 ++ .../insights/common/schemas/PurchaseEvent.yml | 2 + .../common/schemas/PurchasedObjectIDs.yml | 33 +++++++++ .../schemas/PurchasedObjectIDsAfterSearch.yml | 35 ++++++++++ templates/dart/tests/param_value.mustache | 2 +- .../methods/requests/insights/pushEvents.json | 67 +++++++++++++++++++ 14 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 generators/src/main/java/com/algolia/codegen/cts/lambda/EscapeDollarLambda.java delete mode 100644 specs/insights/common/enums.yml create mode 100644 specs/insights/common/schemas/AddToCartEvent.yml create mode 100644 specs/insights/common/schemas/AddedToCartObjectIDs.yml create mode 100644 specs/insights/common/schemas/AddedToCartObjectIDsAfterSearch.yml create mode 100644 specs/insights/common/schemas/PurchaseEvent.yml create mode 100644 specs/insights/common/schemas/PurchasedObjectIDs.yml create mode 100644 specs/insights/common/schemas/PurchasedObjectIDsAfterSearch.yml diff --git a/generators/src/main/java/com/algolia/codegen/cts/AlgoliaCTSGenerator.java b/generators/src/main/java/com/algolia/codegen/cts/AlgoliaCTSGenerator.java index 75eca6f28f..a8e4d4107a 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/AlgoliaCTSGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/cts/AlgoliaCTSGenerator.java @@ -83,6 +83,7 @@ public Map postProcessAllModels(Map objs) protected Builder addMustacheLambdas() { Builder lambdas = super.addMustacheLambdas(); + lambdas.put("escapeDollar", new EscapeDollarLambda()); lambdas.put("escapeQuotes", new EscapeQuotesLambda()); lambdas.put("escapeSlash", new EscapeSlashLambda()); lambdas.put("replaceBacktick", new ReplaceBacktickLambda()); diff --git a/generators/src/main/java/com/algolia/codegen/cts/lambda/EscapeDollarLambda.java b/generators/src/main/java/com/algolia/codegen/cts/lambda/EscapeDollarLambda.java new file mode 100644 index 0000000000..1f56175af4 --- /dev/null +++ b/generators/src/main/java/com/algolia/codegen/cts/lambda/EscapeDollarLambda.java @@ -0,0 +1,15 @@ +package com.algolia.codegen.cts.lambda; + +import com.samskivert.mustache.Mustache; +import com.samskivert.mustache.Template; +import java.io.IOException; +import java.io.Writer; + +public class EscapeDollarLambda implements Mustache.Lambda { + + @Override + public void execute(Template.Fragment fragment, Writer writer) throws IOException { + String text = fragment.execute(); + writer.write(text.replace("$", "\\$")); + } +} diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java index fb89056029..7bdd65fd6e 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java @@ -88,6 +88,16 @@ public void run(Map models, Map req.request.body = "{}"; } + // For golang, jsonassert expect % to be formatted, we need to escape them + if (language.equals("go") && req.request.body != null) { + req.request.body = req.request.body.replace("%", "%%"); + } + + // For dart, same thing but for $ + if (language.equals("dart") && req.request.body != null) { + req.request.body = req.request.body.replace("$", "\\$"); + } + // In a case of a `GET` or `DELETE` request, we want to assert if the body // is correctly parsed (absent from the payload) if (req.request.method.equals("GET") || req.request.method.equals("DELETE")) { diff --git a/specs/insights/common/enums.yml b/specs/insights/common/enums.yml deleted file mode 100644 index 736bf66da4..0000000000 --- a/specs/insights/common/enums.yml +++ /dev/null @@ -1,3 +0,0 @@ -eventType: - type: string - enum: [click, conversion, view] diff --git a/specs/insights/common/schemas/AddToCartEvent.yml b/specs/insights/common/schemas/AddToCartEvent.yml new file mode 100644 index 0000000000..1852baec58 --- /dev/null +++ b/specs/insights/common/schemas/AddToCartEvent.yml @@ -0,0 +1,2 @@ +type: string +enum: [addToCart] diff --git a/specs/insights/common/schemas/AddedToCartObjectIDs.yml b/specs/insights/common/schemas/AddedToCartObjectIDs.yml new file mode 100644 index 0000000000..44b699a8dc --- /dev/null +++ b/specs/insights/common/schemas/AddedToCartObjectIDs.yml @@ -0,0 +1,33 @@ +type: object +title: Added to cart object IDs +description: | + Use this event to track when users add items to their shopping cart unrelated to a previous Algolia request. For example, if you don't use Algolia to build your category pages, use this event. + + To track add-to-cart events related to Algolia requests, use the "Added to cart object IDs after search" event. +additionalProperties: false +properties: + eventName: + $ref: './EventAttributes.yml#/eventName' + eventType: + $ref: './ConversionEvent.yml' + eventSubtype: + $ref: './AddToCartEvent.yml' + index: + $ref: './EventAttributes.yml#/index' + objectIDs: + $ref: './EventAttributes.yml#/objectIDs' + objectData: + $ref: './EventAttributes.yml#/objectDataList' + currency: + $ref: './EventAttributes.yml#/currency' + userToken: + $ref: './EventAttributes.yml#/userToken' + timestamp: + $ref: './EventAttributes.yml#/timestamp' +required: + - eventName + - eventType + - eventSubtype + - index + - objectIDs + - userToken diff --git a/specs/insights/common/schemas/AddedToCartObjectIDsAfterSearch.yml b/specs/insights/common/schemas/AddedToCartObjectIDsAfterSearch.yml new file mode 100644 index 0000000000..02cb781103 --- /dev/null +++ b/specs/insights/common/schemas/AddedToCartObjectIDsAfterSearch.yml @@ -0,0 +1,35 @@ +type: object +title: Added to cart object IDs after search +description: | + Use this event to track when users add items to their shopping cart after a previous Algolia request. + If you're building your category pages with Algolia, you'll also use this event. +additionalProperties: false +properties: + eventName: + $ref: './EventAttributes.yml#/eventName' + eventType: + $ref: './ConversionEvent.yml' + eventSubtype: + $ref: './AddToCartEvent.yml' + index: + $ref: './EventAttributes.yml#/index' + queryID: + $ref: './EventAttributes.yml#/queryID' + objectIDs: + $ref: './EventAttributes.yml#/objectIDs' + objectData: + $ref: './EventAttributes.yml#/objectDataAfterSearchList' + currency: + $ref: './EventAttributes.yml#/currency' + userToken: + $ref: './EventAttributes.yml#/userToken' + timestamp: + $ref: './EventAttributes.yml#/timestamp' +required: + - eventName + - eventType + - eventSubtype + - queryID + - index + - objectIDs + - userToken diff --git a/specs/insights/common/schemas/EventAttributes.yml b/specs/insights/common/schemas/EventAttributes.yml index ff78563f5a..b74c27ba7f 100644 --- a/specs/insights/common/schemas/EventAttributes.yml +++ b/specs/insights/common/schemas/EventAttributes.yml @@ -2,6 +2,7 @@ eventName: type: string minLength: 1 maxLength: 64 + pattern: '[\x20-\x7E]{1,64}' description: | Can contain up to 64 ASCII characters. @@ -81,3 +82,68 @@ positions: The first search result has a position of 1 (not 0). You must provide 1 `position` for each `objectID`. example: [1, 2, 5] + +price: + description: The price of the item. This should be the final price, inclusive of any discounts in effect. + oneOf: + - type: number + format: double + - type: string + +discount: + description: Absolute value of the discount in effect for this object, measured in `currency`. + oneOf: + - type: number + format: double + - type: string + +objectData: + type: object + additionalProperties: false + properties: + price: + $ref: '#/price' + quantity: + type: integer + format: int32 + description: The quantity of the purchased or added-to-cart item. The total value of a purchase is the sum of `quantity` multiplied with the `price` for each purchased item. + discount: + $ref: '#/discount' + +objectDataList: + type: array + description: | + Extra information about the records involved in the event—for example, to add price and quantities of purchased products. + + If provided, must be the same length as `objectIDs`. + items: + $ref: '#/objectData' + +objectDataAfterSearch: + type: object + additionalProperties: false + properties: + queryID: + type: string + description: ID of the query that this specific record is attributable to. Used to track purchase events with multiple items originating from different searches. + price: + $ref: '#/price' + quantity: + type: integer + format: int32 + description: The quantity of the purchased or added-to-cart item. The total value of a purchase is the sum of `quantity` multiplied with the `price` for each purchased item. + discount: + $ref: '#/discount' + +objectDataAfterSearchList: + type: array + description: | + Extra information about the records involved in the event—for example, to add price and quantities of purchased products. + + If provided, must be the same length as `objectIDs`. + items: + $ref: '#/objectDataAfterSearch' + +currency: + type: string + description: If you include pricing information in the `objectData` parameter, you must also specify the currency as ISO-4217 currency code, such as USD or EUR. diff --git a/specs/insights/common/schemas/EventsItems.yml b/specs/insights/common/schemas/EventsItems.yml index 2d124379d4..aebabb030a 100644 --- a/specs/insights/common/schemas/EventsItems.yml +++ b/specs/insights/common/schemas/EventsItems.yml @@ -7,3 +7,7 @@ oneOf: - $ref: './ConvertedFilters.yml' - $ref: './ViewedObjectIDs.yml' - $ref: './ViewedFilters.yml' + - $ref: './AddedToCartObjectIDsAfterSearch.yml' + - $ref: './AddedToCartObjectIDs.yml' + - $ref: './PurchasedObjectIDs.yml' + - $ref: './PurchasedObjectIDsAfterSearch.yml' diff --git a/specs/insights/common/schemas/PurchaseEvent.yml b/specs/insights/common/schemas/PurchaseEvent.yml new file mode 100644 index 0000000000..bd5c72ab5b --- /dev/null +++ b/specs/insights/common/schemas/PurchaseEvent.yml @@ -0,0 +1,2 @@ +type: string +enum: [purchase] diff --git a/specs/insights/common/schemas/PurchasedObjectIDs.yml b/specs/insights/common/schemas/PurchasedObjectIDs.yml new file mode 100644 index 0000000000..201c00ec34 --- /dev/null +++ b/specs/insights/common/schemas/PurchasedObjectIDs.yml @@ -0,0 +1,33 @@ +type: object +title: Purchased object IDs +description: | + Use this event to track when users make a purchase unrelated to a previous Algolia request. For example, if you don't use Algolia to build your category pages, use this event. + + To track purchase events related to Algolia requests, use the "Purchased object IDs after search" event. +additionalProperties: false +properties: + eventName: + $ref: './EventAttributes.yml#/eventName' + eventType: + $ref: './ConversionEvent.yml' + eventSubtype: + $ref: './PurchaseEvent.yml' + index: + $ref: './EventAttributes.yml#/index' + objectIDs: + $ref: './EventAttributes.yml#/objectIDs' + objectData: + $ref: './EventAttributes.yml#/objectDataList' + currency: + $ref: './EventAttributes.yml#/currency' + userToken: + $ref: './EventAttributes.yml#/userToken' + timestamp: + $ref: './EventAttributes.yml#/timestamp' +required: + - eventName + - eventType + - eventSubtype + - index + - objectIDs + - userToken diff --git a/specs/insights/common/schemas/PurchasedObjectIDsAfterSearch.yml b/specs/insights/common/schemas/PurchasedObjectIDsAfterSearch.yml new file mode 100644 index 0000000000..ebc9a84166 --- /dev/null +++ b/specs/insights/common/schemas/PurchasedObjectIDsAfterSearch.yml @@ -0,0 +1,35 @@ +type: object +title: Purchased object IDs after search +description: | + Use this event to track when users make a purchase after a previous Algolia request. + If you're building your category pages with Algolia, you'll also use this event. +additionalProperties: false +properties: + eventName: + $ref: './EventAttributes.yml#/eventName' + eventType: + $ref: './ConversionEvent.yml' + eventSubtype: + $ref: './PurchaseEvent.yml' + index: + $ref: './EventAttributes.yml#/index' + queryID: + $ref: './EventAttributes.yml#/queryID' + objectIDs: + $ref: './EventAttributes.yml#/objectIDs' + objectData: + $ref: './EventAttributes.yml#/objectDataAfterSearchList' + currency: + $ref: './EventAttributes.yml#/currency' + userToken: + $ref: './EventAttributes.yml#/userToken' + timestamp: + $ref: './EventAttributes.yml#/timestamp' +required: + - eventName + - eventType + - eventSubtype + - queryID + - index + - objectIDs + - userToken diff --git a/templates/dart/tests/param_value.mustache b/templates/dart/tests/param_value.mustache index a8bc68b26e..b45ac52d67 100644 --- a/templates/dart/tests/param_value.mustache +++ b/templates/dart/tests/param_value.mustache @@ -1,5 +1,5 @@ {{#isNull}}empty(){{/isNull}} -{{#isString}}"{{{value}}}"{{/isString}} +{{#isString}}"{{#lambda.escapeDollar}}{{{value}}}{{/lambda.escapeDollar}}"{{/isString}} {{#isNumber}}{{{value}}}{{/isNumber}} {{#isBoolean}}{{{value}}}{{/isBoolean}} {{#isEnum}}{{{objectName}}}.fromJson("{{value}}"){{/isEnum}} diff --git a/tests/CTS/methods/requests/insights/pushEvents.json b/tests/CTS/methods/requests/insights/pushEvents.json index 267f378580..b95f5a7e06 100644 --- a/tests/CTS/methods/requests/insights/pushEvents.json +++ b/tests/CTS/methods/requests/insights/pushEvents.json @@ -181,5 +181,72 @@ ] } } + }, + { + "testName": "AddedToCartObjectIDs", + "parameters": { + "events": [ + { + "eventType": "conversion", + "eventSubtype": "addToCart", + "eventName": "Product Added To Cart", + "index": "products", + "queryID": "43b15df305339e827f0ac0bdc5ebcaa7", + "userToken": "user-123456", + "timestamp": 1641290601962, + "objectIDs": [ + "9780545139700", + "9780439784542" + ], + "objectData": [ + { + "price": 19.99, + "quantity": 10, + "discount": 2.5 + }, + { + "price": "8$", + "quantity": 7, + "discount": "30%" + } + ], + "currency": "USD" + } + ] + }, + "request": { + "path": "/1/events", + "method": "POST", + "body": { + "events": [ + { + "eventType": "conversion", + "eventSubtype": "addToCart", + "eventName": "Product Added To Cart", + "index": "products", + "queryID": "43b15df305339e827f0ac0bdc5ebcaa7", + "userToken": "user-123456", + "timestamp": 1641290601962, + "objectIDs": [ + "9780545139700", + "9780439784542" + ], + "objectData": [ + { + "price": 19.99, + "quantity": 10, + "discount": 2.5 + }, + { + "price": "8$", + "quantity": 7, + "discount": "30%" + } + ], + "currency": "USD" + } + ] + } + } } ]