@@ -26,6 +26,7 @@ The Airship SDK 20.0 introduces major architectural changes including the renami
2626 - [ Minor Push Notification Changes] ( #minor-push-notification-changes )
2727 - [ Permissions Manager API Changes] ( #permissions-manager-api-changes )
2828 - [ Action Framework Changes] ( #action-framework-changes )
29+ - [ Event Template Changes] ( #event-template-changes )
2930- [ Deprecated APIs] ( #deprecated-apis )
3031 - [ UAirship Deprecated] ( #uairship-deprecated )
3132 - [ Autopilot Signature Change] ( #autopilot-signature-change )
@@ -242,6 +243,197 @@ Airship.actionRegistry.registerEntry(setOf("my_action")) {
242243}
243244```
244245
246+ ### Event Template Changes
247+
248+ The event template classes (` RetailEventTemplate ` , ` MediaEventTemplate ` , ` AccountEventTemplate ` , ` SearchEventTemplate ` ) have been redesigned. The old template classes that combined properties and event creation have been replaced with a new architecture that separates concerns into ` Type ` and ` Properties ` classes, with event creation handled by ` CustomEvent ` .
249+
250+ #### Package Change
251+
252+ All event templates have moved to a new package:
253+
254+ | SDK 19.x | SDK 20.x |
255+ | ---| ---|
256+ | ` com.urbanairship.analytics.RetailEventTemplate ` | ` com.urbanairship.analytics.templates.RetailEventTemplate ` |
257+ | ` com.urbanairship.analytics.MediaEventTemplate ` | ` com.urbanairship.analytics.templates.MediaEventTemplate ` |
258+ | ` com.urbanairship.analytics.AccountEventTemplate ` | ` com.urbanairship.analytics.templates.AccountEventTemplate ` |
259+ | ` com.urbanairship.analytics.SearchEventTemplate ` | ` com.urbanairship.analytics.templates.SearchEventTemplate ` |
260+
261+ #### API Changes
262+
263+ In SDK 19.x, templates were created via factory methods, properties were set directly on the template, and events were created from the template. In SDK 20.x, this is split into:
264+
265+ 1 . ** ` Type ` ** — a sealed class (or enum) that defines the event situation (e.g., ` Purchased ` , ` AddedToCart ` )
266+ 2 . ** ` Properties ` ** — a data class holding template-specific fields (e.g., category, brand, description)
267+ 3 . ** ` CustomEvent.newBuilder(type, properties) ` ** — creates the event, with event-level fields like ` eventValue ` and ` transactionId ` set on the builder
268+
269+ ##### Retail Event Template
270+
271+ | SDK 19.x Factory Method | SDK 20.x Type |
272+ | ---| ---|
273+ | ` RetailEventTemplate.newPurchasedTemplate() ` | ` RetailEventTemplate.Type.Purchased ` |
274+ | ` RetailEventTemplate.newAddedToCartTemplate() ` | ` RetailEventTemplate.Type.AddedToCart ` |
275+ | ` RetailEventTemplate.newBrowsedTemplate() ` | ` RetailEventTemplate.Type.Browsed ` |
276+ | ` RetailEventTemplate.newStarredProductTemplate() ` | ` RetailEventTemplate.Type.Starred ` |
277+ | ` RetailEventTemplate.newSharedTemplate(source, medium) ` | ` RetailEventTemplate.Type.Shared(source, medium) ` |
278+ | ` RetailEventTemplate.newWishlistTemplate(id, name) ` | ` RetailEventTemplate.Type.Wishlist(id, name) ` |
279+
280+ | SDK 19.x Template Method | SDK 20.x Location |
281+ | ---| ---|
282+ | ` template.setCategory(...) ` | ` RetailEventTemplate.Properties(category = ...) ` |
283+ | ` template.setId(...) ` | ` RetailEventTemplate.Properties(id = ...) ` |
284+ | ` template.setDescription(...) ` | ` RetailEventTemplate.Properties(eventDescription = ...) ` |
285+ | ` template.setBrand(...) ` | ` RetailEventTemplate.Properties(brand = ...) ` |
286+ | ` template.setValue(...) ` | ` CustomEvent.Builder.setEventValue(...) ` |
287+ | ` template.setTransactionId(...) ` | ` CustomEvent.Builder.setTransactionId(...) ` |
288+ | ` template.createEvent() ` | ` CustomEvent.newBuilder(type, properties).build() ` |
289+
290+ ###### Java
291+ ``` java
292+ // SDK 19.x
293+ RetailEventTemplate template = RetailEventTemplate . newPurchasedTemplate();
294+ template. setCategory(" shoes" )
295+ .setId(" sku-123" )
296+ .setDescription(" Running Shoes" )
297+ .setBrand(" Nike" )
298+ .setValue(99.99 )
299+ .setTransactionId(" txn-456" )
300+ .createEvent()
301+ .track();
302+
303+ // SDK 20.x
304+ RetailEventTemplate . Properties properties = RetailEventTemplate . Properties . newBuilder()
305+ .setId(" sku-123" )
306+ .setCategory(" shoes" )
307+ .setDescription(" Running Shoes" )
308+ .setBrand(" Nike" )
309+ .build();
310+
311+ CustomEvent . newBuilder(RetailEventTemplate . Type . Purchased , properties)
312+ .setEventValue(99.99 )
313+ .setTransactionId(" txn-456" )
314+ .build()
315+ .track();
316+ ```
317+
318+ ###### Kotlin
319+ ``` kotlin
320+ // SDK 19.x
321+ RetailEventTemplate .newPurchasedTemplate()
322+ .setCategory(" shoes" )
323+ .setId(" sku-123" )
324+ .setDescription(" Running Shoes" )
325+ .setBrand(" Nike" )
326+ .setValue(99.99 )
327+ .setTransactionId(" txn-456" )
328+ .createEvent()
329+ .track()
330+
331+ // SDK 20.x
332+ customEvent(
333+ RetailEventTemplate .Type .Purchased ,
334+ RetailEventTemplate .Properties (
335+ id = " sku-123" ,
336+ category = " shoes" ,
337+ eventDescription = " Running Shoes" ,
338+ brand = " Nike"
339+ )
340+ ) {
341+ setEventValue(99.99 )
342+ setTransactionId(" txn-456" )
343+ }.track()
344+ ```
345+
346+ ##### Media Event Template
347+
348+ | SDK 19.x Factory Method | SDK 20.x Type |
349+ | ---| ---|
350+ | ` MediaEventTemplate.newBrowsedTemplate() ` | ` MediaEventTemplate.Type.Browsed ` |
351+ | ` MediaEventTemplate.newConsumedTemplate() ` | ` MediaEventTemplate.Type.Consumed ` |
352+ | ` MediaEventTemplate.newStarredTemplate() ` | ` MediaEventTemplate.Type.Starred ` |
353+ | ` MediaEventTemplate.newSharedTemplate(source, medium) ` | ` MediaEventTemplate.Type.Shared(source, medium) ` |
354+
355+ ###### Kotlin
356+ ``` kotlin
357+ // SDK 19.x
358+ MediaEventTemplate .newConsumedTemplate()
359+ .setCategory(" podcasts" )
360+ .setId(" episode-123" )
361+ .setDescription(" Tech Talk #42" )
362+ .setAuthor(" Jane Doe" )
363+ .setValue(1.0 )
364+ .createEvent()
365+ .track()
366+
367+ // SDK 20.x
368+ customEvent(
369+ MediaEventTemplate .Type .Consumed ,
370+ MediaEventTemplate .Properties (
371+ id = " episode-123" ,
372+ category = " podcasts" ,
373+ eventDescription = " Tech Talk #42" ,
374+ author = " Jane Doe"
375+ )
376+ ) {
377+ setEventValue(1.0 )
378+ }.track()
379+ ```
380+
381+ ##### Account Event Template
382+
383+ | SDK 19.x Factory Method | SDK 20.x Type |
384+ | ---| ---|
385+ | ` AccountEventTemplate.newRegisteredTemplate() ` | ` AccountEventTemplate.Type.REGISTERED ` |
386+ | ` AccountEventTemplate.newLoggedInTemplate() ` | ` AccountEventTemplate.Type.LOGGED_IN ` |
387+ | ` AccountEventTemplate.newLoggedOutTemplate() ` | ` AccountEventTemplate.Type.LOGGED_OUT ` |
388+
389+ ###### Kotlin
390+ ``` kotlin
391+ // SDK 19.x
392+ AccountEventTemplate .newRegisteredTemplate()
393+ .setCategory(" premium" )
394+ .setValue(9.99 )
395+ .createEvent()
396+ .track()
397+
398+ // SDK 20.x
399+ customEvent(
400+ AccountEventTemplate .Type .REGISTERED ,
401+ AccountEventTemplate .Properties (category = " premium" )
402+ ) {
403+ setEventValue(9.99 )
404+ }.track()
405+ ```
406+
407+ ##### Search Event Template
408+
409+ | SDK 19.x Factory Method | SDK 20.x Type |
410+ | ---| ---|
411+ | ` SearchEventTemplate.newSearchTemplate() ` | ` SearchEventTemplate.Type.SEARCH ` |
412+
413+ ###### Kotlin
414+ ``` kotlin
415+ // SDK 19.x
416+ SearchEventTemplate .newSearchTemplate()
417+ .setCategory(" hotels" )
418+ .setQuery(" beach resort" )
419+ .setTotalResults(53 )
420+ .setValue(1.0 )
421+ .createEvent()
422+ .track()
423+
424+ // SDK 20.x
425+ customEvent(
426+ SearchEventTemplate .Type .SEARCH ,
427+ SearchEventTemplate .Properties (
428+ category = " hotels" ,
429+ query = " beach resort" ,
430+ totalResults = 53
431+ )
432+ ) {
433+ setEventValue(1.0 )
434+ }.track()
435+ ```
436+
245437## Deprecated APIs
246438
247439### UAirship Deprecated
0 commit comments