@admoai/sdk-scenarios 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/scenarios.feature +148 -2
- package/scenarios.json +630 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ Versioning: a scenario added or an `expect` tightened is a **minor** release; a
|
|
|
4
4
|
removed, or a `request`/`expect` key renamed (every SDK's interpreter must change), is a
|
|
5
5
|
**major** one. Each SDK vendors one version and its own CI checks the vendored bytes against it.
|
|
6
6
|
|
|
7
|
+
## 1.3.0 — 2026-11-05
|
|
8
|
+
|
|
9
|
+
Adds fixture scenarios F16–F25 with a `slideTracking` block (admoai/adhub#4733): what the app
|
|
10
|
+
dispatches when it reports slides and interactions on a decoded standard creative, offline.
|
|
11
|
+
A slide view goes out once per served response, keyed on its signed URL, and again for a new
|
|
12
|
+
response (F16, F17). A slide click before its view sends the view, then the click, then the
|
|
13
|
+
creative's applicable third-party click trackers once per click. A slide view never sends them
|
|
14
|
+
(F18-F20). A Carousel has no creative click (F21). `fireClick` with no key sends `default`
|
|
15
|
+
(F22). Expand, close and asset tap are verbatim custom events, not clicks (F23, F24). A
|
|
16
|
+
Standard Video without a destination sends no click (F25). New edit level `tracking` (the
|
|
17
|
+
creative's tracking object), used to inject third-party trackers on `.example` hosts. A
|
|
18
|
+
`schemaVersion` moves to 3, so a runner that knows only 2 refuses the manifest instead of
|
|
19
|
+
skipping `slideTracking` silently; adopting 1.3.0 requires executing it.
|
|
20
|
+
|
|
7
21
|
## 1.2.0 — 2026-11-05
|
|
8
22
|
|
|
9
23
|
Adds `fixtureScenarios` F1–F15 and moves `schemaVersion` to 2 (admoai/adhub#4733): offline
|
package/package.json
CHANGED
package/scenarios.feature
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# promises a publisher's app, in the same words for all three. CI regenerates it and fails on
|
|
7
7
|
# any difference, so it cannot drift from what the runners execute.
|
|
8
8
|
# How it is published and kept fresh: docs/guides/sdk-ci.md, Section 7.
|
|
9
|
-
# Manifest schemaVersion:
|
|
9
|
+
# Manifest schemaVersion: 3
|
|
10
10
|
|
|
11
11
|
Feature: Cross-SDK decision & tracking contract
|
|
12
12
|
Shared cross-SDK E2E scenario manifest. ONE definition, executed by a thin interpreter in each
|
|
@@ -22,7 +22,15 @@ Feature: Cross-SDK decision & tracking contract
|
|
|
22
22
|
reads from the decoded creative. `contentKeys` is the exact set of plain content keys (slides
|
|
23
23
|
and matched points are asserted through their own fields); a key in `contentKeysAbsent` must
|
|
24
24
|
decode as absent (null), never as an empty string or a placeholder; a null in `metadata` means
|
|
25
|
-
absent. A runner that does not execute fixtureScenarios must refuse schemaVersion 2.
|
|
25
|
+
absent. A runner that does not execute fixtureScenarios must refuse schemaVersion 2. A fixture
|
|
26
|
+
scenario may add `slideTracking` (package 1.3.0, schemaVersion 3; a runner that does not
|
|
27
|
+
execute it must refuse schemaVersion 3): `steps` the app takes on the decoded creative
|
|
28
|
+
(`slideView`/`slideClick` with a 1-based slide index, `newResponse`, `fireClick` with a key or
|
|
29
|
+
null for no key, `custom` with a key) and the beacons that must be dispatched: `beacons` is
|
|
30
|
+
the exact ordered list of first-party beacons, each named by the tracker it must be
|
|
31
|
+
(`slide`+`view`/`click`, or creative `click`/`custom`, with `response`), and
|
|
32
|
+
`thirdPartyBeacons` the exact multiset of third-party tracker ids dispatched (their order is
|
|
33
|
+
not asserted). An edit `at` `tracking` targets the creative's tracking object.
|
|
26
34
|
|
|
27
35
|
@L @native
|
|
28
36
|
Scenario: L1 — a normal native ad serves with complete, well-formed metadata
|
|
@@ -595,3 +603,141 @@ Feature: Cross-SDK decision & tracking contract
|
|
|
595
603
|
And slide 1 is "slide_01JDY02N8MA2K2HKQ74989YS99" with contents "image", "headline", "supporting_text", "cta_text", "destination_url", view trackers "slide_view" and click trackers "default"
|
|
596
604
|
And slide 2 is "slide_01JD04H8GY801VF8Y0FHETP6XA" with contents "image", "headline", "supporting_text", "cta_text", "destination_url", view trackers "slide_view" and click trackers "default"
|
|
597
605
|
And slide 3 is "slide_01JDRGMFSTZXQ7ES1QBCF0DR2X" with contents "image", "headline", "supporting_text", "cta_text", "destination_url", view trackers "slide_view" and click trackers "default"
|
|
606
|
+
|
|
607
|
+
@F @fixture
|
|
608
|
+
Scenario: F16 — a slide's view beacon is sent once per served response, however often the slide is shown
|
|
609
|
+
Keyed on the signed view URL, never on the slideId: re-rendering or scrolling back to a
|
|
610
|
+
slide must not count it again (BR-SDK-04, Q19).
|
|
611
|
+
|
|
612
|
+
Given the app decodes the golden carousel.full response
|
|
613
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
614
|
+
When the app reports slide 1 as viewed
|
|
615
|
+
And the app reports slide 1 as viewed
|
|
616
|
+
And the app reports slide 2 as viewed
|
|
617
|
+
And the app reports slide 1 as viewed
|
|
618
|
+
Then the response decodes
|
|
619
|
+
And exactly these beacons are sent, in this order:
|
|
620
|
+
And slide 1's "slide_view" view beacon
|
|
621
|
+
And slide 2's "slide_view" view beacon
|
|
622
|
+
And no third-party tracker is sent
|
|
623
|
+
|
|
624
|
+
@F @fixture
|
|
625
|
+
Scenario: F17 — the same slide in a new decision response counts again
|
|
626
|
+
A new response carries new signed URLs for the same slides. The runner simulates it by
|
|
627
|
+
decoding the same golden file again with every first-party tracker URL suffixed
|
|
628
|
+
`&response=N` (N = 2, 3, ...); `response` in an expected beacon names which one (default 1).
|
|
629
|
+
|
|
630
|
+
Given the app decodes the golden carousel.full response
|
|
631
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
632
|
+
When the app reports slide 1 as viewed
|
|
633
|
+
And the app decodes a new decision response for the same ad
|
|
634
|
+
And the app reports slide 1 as viewed
|
|
635
|
+
And the app reports slide 1 as viewed
|
|
636
|
+
Then the response decodes
|
|
637
|
+
And exactly these beacons are sent, in this order:
|
|
638
|
+
And slide 1's "slide_view" view beacon
|
|
639
|
+
And slide 1's "slide_view" view beacon from response 2
|
|
640
|
+
And no third-party tracker is sent
|
|
641
|
+
|
|
642
|
+
@F @fixture
|
|
643
|
+
Scenario: F18 — a slide clicked before its view was sent sends the view, then the click, then the creative's applicable third-party click trackers once
|
|
644
|
+
Applicable means a click tracker matching any click, or the `default` click specifically; a
|
|
645
|
+
tracker for another click key and an impression tracker do not fire (BR-SDK-05, Q14, Q18).
|
|
646
|
+
|
|
647
|
+
Given the app decodes the golden carousel.full response
|
|
648
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
649
|
+
When the user clicks slide 2
|
|
650
|
+
Then the response decodes
|
|
651
|
+
And exactly these beacons are sent, in this order:
|
|
652
|
+
And slide 2's "slide_view" view beacon
|
|
653
|
+
And slide 2's "default" click beacon
|
|
654
|
+
And the third-party trackers sent are exactly "tpt_fixture_click_any", "tpt_fixture_click_default"
|
|
655
|
+
|
|
656
|
+
@F @fixture
|
|
657
|
+
Scenario: F19 — a slide clicked after its view sends only the click, on every click
|
|
658
|
+
Given the app decodes the golden carousel.full response
|
|
659
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
660
|
+
When the app reports slide 2 as viewed
|
|
661
|
+
And the user clicks slide 2
|
|
662
|
+
And the user clicks slide 2
|
|
663
|
+
Then the response decodes
|
|
664
|
+
And exactly these beacons are sent, in this order:
|
|
665
|
+
And slide 2's "slide_view" view beacon
|
|
666
|
+
And slide 2's "default" click beacon
|
|
667
|
+
And slide 2's "default" click beacon
|
|
668
|
+
And the third-party trackers sent are exactly "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_any", "tpt_fixture_click_default"
|
|
669
|
+
|
|
670
|
+
@F @fixture
|
|
671
|
+
Scenario: F20 — slide views never send third-party click trackers
|
|
672
|
+
Given the app decodes the golden carousel.full response
|
|
673
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
674
|
+
When the app reports slide 1 as viewed
|
|
675
|
+
And the app reports slide 2 as viewed
|
|
676
|
+
And the app reports slide 3 as viewed
|
|
677
|
+
Then the response decodes
|
|
678
|
+
And exactly these beacons are sent, in this order:
|
|
679
|
+
And slide 1's "slide_view" view beacon
|
|
680
|
+
And slide 2's "slide_view" view beacon
|
|
681
|
+
And slide 3's "slide_view" view beacon
|
|
682
|
+
And no third-party tracker is sent
|
|
683
|
+
|
|
684
|
+
@F @fixture
|
|
685
|
+
Scenario: F21 — a Carousel has no creative-level click: fireClick sends nothing, so slide clicks go through the slide helper
|
|
686
|
+
Publishers must not route a slide tap through fireClick (BR-SDK-03, Q9).
|
|
687
|
+
|
|
688
|
+
Given the app decodes the golden carousel.full response
|
|
689
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
690
|
+
When the app calls fireClick with no key
|
|
691
|
+
Then the response decodes
|
|
692
|
+
And no first-party beacon is sent
|
|
693
|
+
And no third-party tracker is sent
|
|
694
|
+
|
|
695
|
+
@F @fixture
|
|
696
|
+
Scenario: F22 — fireClick with no key sends the default click of a standard
|
|
697
|
+
Every standard seeds its click with key `default`, which is what fireClick sends without a
|
|
698
|
+
key (BR-SDK-06, Q12).
|
|
699
|
+
|
|
700
|
+
Given the app decodes the golden card.full response
|
|
701
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
702
|
+
When the app calls fireClick with no key
|
|
703
|
+
Then the response decodes
|
|
704
|
+
And exactly these beacons are sent, in this order:
|
|
705
|
+
And the creative's "default" click beacon
|
|
706
|
+
And the third-party trackers sent are exactly "tpt_fixture_click_any", "tpt_fixture_click_default"
|
|
707
|
+
|
|
708
|
+
@F @fixture
|
|
709
|
+
Scenario: F23 — expand and close are sent verbatim as custom events and are not clicks
|
|
710
|
+
The publisher calls them when the banner actually expands or closes; no click is sent and no
|
|
711
|
+
third-party click tracker fires (BR-SDK-07).
|
|
712
|
+
|
|
713
|
+
Given the app decodes the golden expandable_banner.full response
|
|
714
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
715
|
+
When the app sends the custom event "expand"
|
|
716
|
+
And the app sends the custom event "close"
|
|
717
|
+
Then the response decodes
|
|
718
|
+
And exactly these beacons are sent, in this order:
|
|
719
|
+
And the creative's "expand" custom beacon
|
|
720
|
+
And the creative's "close" custom beacon
|
|
721
|
+
And no third-party tracker is sent
|
|
722
|
+
|
|
723
|
+
@F @fixture
|
|
724
|
+
Scenario: F24 — an asset tap is sent verbatim as a custom event and is not a click
|
|
725
|
+
BR-SDK-07.
|
|
726
|
+
|
|
727
|
+
Given the app decodes the golden branded_assets.full response
|
|
728
|
+
And with third-party trackers "tpt_fixture_click_any", "tpt_fixture_click_default", "tpt_fixture_click_other", "tpt_fixture_impression"
|
|
729
|
+
When the app sends the custom event "asset_tap"
|
|
730
|
+
Then the response decodes
|
|
731
|
+
And exactly these beacons are sent, in this order:
|
|
732
|
+
And the creative's "asset_tap" custom beacon
|
|
733
|
+
And no third-party tracker is sent
|
|
734
|
+
|
|
735
|
+
@F @fixture
|
|
736
|
+
Scenario: F25 — a Standard Video without a destination sends no click
|
|
737
|
+
No destination means no click action and no click tracker (BR-SDK-08).
|
|
738
|
+
|
|
739
|
+
Given the app decodes the golden standard_video.minimal response
|
|
740
|
+
When the app calls fireClick with no key
|
|
741
|
+
Then the response decodes
|
|
742
|
+
And no first-party beacon is sent
|
|
743
|
+
And no third-party tracker is sent
|
package/scenarios.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"schemaVersion":
|
|
3
|
-
"description": "Shared cross-SDK E2E scenario manifest. ONE definition, executed by a thin interpreter in each SDK, so the three suites cannot drift. Declarative only: given a request, expect an outcome. Sponsored Pin tracking scenarios add `pinTracking`: the point-tracking calls an app makes on the served pins, as data, and the beacons that must reach the engine. Procedural scenarios (log capture, concurrency, retry, TTL waits) stay hand-written per SDK. Mirrored byte-identically into all three repos; a checksum test fails the build if the copies diverge. Every expected value here was verified against a live local decision-engine before being written. `fixtureScenarios` (schemaVersion 2) run offline: each decodes one golden decision-wire file (ui/platform/lib/ad-formats/golden-wire in adhub, shipped in this package under fixtures/golden-wire/) after optional `edits`, and asserts what the publisher's app reads from the decoded creative. `contentKeys` is the exact set of plain content keys (slides and matched points are asserted through their own fields); a key in `contentKeysAbsent` must decode as absent (null), never as an empty string or a placeholder; a null in `metadata` means absent. A runner that does not execute fixtureScenarios must refuse schemaVersion 2.",
|
|
2
|
+
"schemaVersion": 3,
|
|
3
|
+
"description": "Shared cross-SDK E2E scenario manifest. ONE definition, executed by a thin interpreter in each SDK, so the three suites cannot drift. Declarative only: given a request, expect an outcome. Sponsored Pin tracking scenarios add `pinTracking`: the point-tracking calls an app makes on the served pins, as data, and the beacons that must reach the engine. Procedural scenarios (log capture, concurrency, retry, TTL waits) stay hand-written per SDK. Mirrored byte-identically into all three repos; a checksum test fails the build if the copies diverge. Every expected value here was verified against a live local decision-engine before being written. `fixtureScenarios` (schemaVersion 2) run offline: each decodes one golden decision-wire file (ui/platform/lib/ad-formats/golden-wire in adhub, shipped in this package under fixtures/golden-wire/) after optional `edits`, and asserts what the publisher's app reads from the decoded creative. `contentKeys` is the exact set of plain content keys (slides and matched points are asserted through their own fields); a key in `contentKeysAbsent` must decode as absent (null), never as an empty string or a placeholder; a null in `metadata` means absent. A runner that does not execute fixtureScenarios must refuse schemaVersion 2. A fixture scenario may add `slideTracking` (package 1.3.0, schemaVersion 3; a runner that does not execute it must refuse schemaVersion 3): `steps` the app takes on the decoded creative (`slideView`/`slideClick` with a 1-based slide index, `newResponse`, `fireClick` with a key or null for no key, `custom` with a key) and the beacons that must be dispatched: `beacons` is the exact ordered list of first-party beacons, each named by the tracker it must be (`slide`+`view`/`click`, or creative `click`/`custom`, with `response`), and `thirdPartyBeacons` the exact multiset of third-party tracker ids dispatched (their order is not asserted). An edit `at` `tracking` targets the creative's tracking object.",
|
|
4
4
|
"scenarios": [
|
|
5
5
|
{
|
|
6
6
|
"id": "L1",
|
|
@@ -1591,6 +1591,634 @@
|
|
|
1591
1591
|
}
|
|
1592
1592
|
]
|
|
1593
1593
|
}
|
|
1594
|
+
},
|
|
1595
|
+
{
|
|
1596
|
+
"id": "F16",
|
|
1597
|
+
"title": "a slide's view beacon is sent once per served response, however often the slide is shown",
|
|
1598
|
+
"comment": "Keyed on the signed view URL, never on the slideId: re-rendering or scrolling back to a slide must not count it again (BR-SDK-04, Q19).",
|
|
1599
|
+
"fixture": {
|
|
1600
|
+
"golden": "carousel.full",
|
|
1601
|
+
"edits": [
|
|
1602
|
+
{
|
|
1603
|
+
"at": "tracking",
|
|
1604
|
+
"add": "thirdPartyTrackers",
|
|
1605
|
+
"value": [
|
|
1606
|
+
{
|
|
1607
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1608
|
+
"eventType": "click",
|
|
1609
|
+
"matchType": "any",
|
|
1610
|
+
"url": "https://adserver.example/click?c=any"
|
|
1611
|
+
},
|
|
1612
|
+
{
|
|
1613
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1614
|
+
"eventType": "click",
|
|
1615
|
+
"matchType": "specific",
|
|
1616
|
+
"eventKey": "default",
|
|
1617
|
+
"url": "https://adserver.example/click?c=default"
|
|
1618
|
+
},
|
|
1619
|
+
{
|
|
1620
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1621
|
+
"eventType": "click",
|
|
1622
|
+
"matchType": "specific",
|
|
1623
|
+
"eventKey": "save_offer",
|
|
1624
|
+
"url": "https://adserver.example/click?c=other"
|
|
1625
|
+
},
|
|
1626
|
+
{
|
|
1627
|
+
"trackerId": "tpt_fixture_impression",
|
|
1628
|
+
"eventType": "impression",
|
|
1629
|
+
"url": "https://adserver.example/imp"
|
|
1630
|
+
}
|
|
1631
|
+
]
|
|
1632
|
+
}
|
|
1633
|
+
]
|
|
1634
|
+
},
|
|
1635
|
+
"expect": {
|
|
1636
|
+
"decodes": true
|
|
1637
|
+
},
|
|
1638
|
+
"slideTracking": {
|
|
1639
|
+
"steps": [
|
|
1640
|
+
{
|
|
1641
|
+
"slideView": 1
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
"slideView": 1
|
|
1645
|
+
},
|
|
1646
|
+
{
|
|
1647
|
+
"slideView": 2
|
|
1648
|
+
},
|
|
1649
|
+
{
|
|
1650
|
+
"slideView": 1
|
|
1651
|
+
}
|
|
1652
|
+
],
|
|
1653
|
+
"expect": {
|
|
1654
|
+
"beacons": [
|
|
1655
|
+
{
|
|
1656
|
+
"slide": 1,
|
|
1657
|
+
"view": "slide_view"
|
|
1658
|
+
},
|
|
1659
|
+
{
|
|
1660
|
+
"slide": 2,
|
|
1661
|
+
"view": "slide_view"
|
|
1662
|
+
}
|
|
1663
|
+
],
|
|
1664
|
+
"thirdPartyBeacons": []
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
"id": "F17",
|
|
1670
|
+
"title": "the same slide in a new decision response counts again",
|
|
1671
|
+
"comment": "A new response carries new signed URLs for the same slides. The runner simulates it by decoding the same golden file again with every first-party tracker URL suffixed `&response=N` (N = 2, 3, ...); `response` in an expected beacon names which one (default 1).",
|
|
1672
|
+
"fixture": {
|
|
1673
|
+
"golden": "carousel.full",
|
|
1674
|
+
"edits": [
|
|
1675
|
+
{
|
|
1676
|
+
"at": "tracking",
|
|
1677
|
+
"add": "thirdPartyTrackers",
|
|
1678
|
+
"value": [
|
|
1679
|
+
{
|
|
1680
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1681
|
+
"eventType": "click",
|
|
1682
|
+
"matchType": "any",
|
|
1683
|
+
"url": "https://adserver.example/click?c=any"
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1687
|
+
"eventType": "click",
|
|
1688
|
+
"matchType": "specific",
|
|
1689
|
+
"eventKey": "default",
|
|
1690
|
+
"url": "https://adserver.example/click?c=default"
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1694
|
+
"eventType": "click",
|
|
1695
|
+
"matchType": "specific",
|
|
1696
|
+
"eventKey": "save_offer",
|
|
1697
|
+
"url": "https://adserver.example/click?c=other"
|
|
1698
|
+
},
|
|
1699
|
+
{
|
|
1700
|
+
"trackerId": "tpt_fixture_impression",
|
|
1701
|
+
"eventType": "impression",
|
|
1702
|
+
"url": "https://adserver.example/imp"
|
|
1703
|
+
}
|
|
1704
|
+
]
|
|
1705
|
+
}
|
|
1706
|
+
]
|
|
1707
|
+
},
|
|
1708
|
+
"expect": {
|
|
1709
|
+
"decodes": true
|
|
1710
|
+
},
|
|
1711
|
+
"slideTracking": {
|
|
1712
|
+
"steps": [
|
|
1713
|
+
{
|
|
1714
|
+
"slideView": 1
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
"newResponse": true
|
|
1718
|
+
},
|
|
1719
|
+
{
|
|
1720
|
+
"slideView": 1
|
|
1721
|
+
},
|
|
1722
|
+
{
|
|
1723
|
+
"slideView": 1
|
|
1724
|
+
}
|
|
1725
|
+
],
|
|
1726
|
+
"expect": {
|
|
1727
|
+
"beacons": [
|
|
1728
|
+
{
|
|
1729
|
+
"slide": 1,
|
|
1730
|
+
"view": "slide_view"
|
|
1731
|
+
},
|
|
1732
|
+
{
|
|
1733
|
+
"slide": 1,
|
|
1734
|
+
"view": "slide_view",
|
|
1735
|
+
"response": 2
|
|
1736
|
+
}
|
|
1737
|
+
],
|
|
1738
|
+
"thirdPartyBeacons": []
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
"id": "F18",
|
|
1744
|
+
"title": "a slide clicked before its view was sent sends the view, then the click, then the creative's applicable third-party click trackers once",
|
|
1745
|
+
"comment": "Applicable means a click tracker matching any click, or the `default` click specifically; a tracker for another click key and an impression tracker do not fire (BR-SDK-05, Q14, Q18).",
|
|
1746
|
+
"fixture": {
|
|
1747
|
+
"golden": "carousel.full",
|
|
1748
|
+
"edits": [
|
|
1749
|
+
{
|
|
1750
|
+
"at": "tracking",
|
|
1751
|
+
"add": "thirdPartyTrackers",
|
|
1752
|
+
"value": [
|
|
1753
|
+
{
|
|
1754
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1755
|
+
"eventType": "click",
|
|
1756
|
+
"matchType": "any",
|
|
1757
|
+
"url": "https://adserver.example/click?c=any"
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1761
|
+
"eventType": "click",
|
|
1762
|
+
"matchType": "specific",
|
|
1763
|
+
"eventKey": "default",
|
|
1764
|
+
"url": "https://adserver.example/click?c=default"
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1768
|
+
"eventType": "click",
|
|
1769
|
+
"matchType": "specific",
|
|
1770
|
+
"eventKey": "save_offer",
|
|
1771
|
+
"url": "https://adserver.example/click?c=other"
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
"trackerId": "tpt_fixture_impression",
|
|
1775
|
+
"eventType": "impression",
|
|
1776
|
+
"url": "https://adserver.example/imp"
|
|
1777
|
+
}
|
|
1778
|
+
]
|
|
1779
|
+
}
|
|
1780
|
+
]
|
|
1781
|
+
},
|
|
1782
|
+
"expect": {
|
|
1783
|
+
"decodes": true
|
|
1784
|
+
},
|
|
1785
|
+
"slideTracking": {
|
|
1786
|
+
"steps": [
|
|
1787
|
+
{
|
|
1788
|
+
"slideClick": 2
|
|
1789
|
+
}
|
|
1790
|
+
],
|
|
1791
|
+
"expect": {
|
|
1792
|
+
"beacons": [
|
|
1793
|
+
{
|
|
1794
|
+
"slide": 2,
|
|
1795
|
+
"view": "slide_view"
|
|
1796
|
+
},
|
|
1797
|
+
{
|
|
1798
|
+
"slide": 2,
|
|
1799
|
+
"click": "default"
|
|
1800
|
+
}
|
|
1801
|
+
],
|
|
1802
|
+
"thirdPartyBeacons": [
|
|
1803
|
+
"tpt_fixture_click_any",
|
|
1804
|
+
"tpt_fixture_click_default"
|
|
1805
|
+
]
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
},
|
|
1809
|
+
{
|
|
1810
|
+
"id": "F19",
|
|
1811
|
+
"title": "a slide clicked after its view sends only the click, on every click",
|
|
1812
|
+
"fixture": {
|
|
1813
|
+
"golden": "carousel.full",
|
|
1814
|
+
"edits": [
|
|
1815
|
+
{
|
|
1816
|
+
"at": "tracking",
|
|
1817
|
+
"add": "thirdPartyTrackers",
|
|
1818
|
+
"value": [
|
|
1819
|
+
{
|
|
1820
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1821
|
+
"eventType": "click",
|
|
1822
|
+
"matchType": "any",
|
|
1823
|
+
"url": "https://adserver.example/click?c=any"
|
|
1824
|
+
},
|
|
1825
|
+
{
|
|
1826
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1827
|
+
"eventType": "click",
|
|
1828
|
+
"matchType": "specific",
|
|
1829
|
+
"eventKey": "default",
|
|
1830
|
+
"url": "https://adserver.example/click?c=default"
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1834
|
+
"eventType": "click",
|
|
1835
|
+
"matchType": "specific",
|
|
1836
|
+
"eventKey": "save_offer",
|
|
1837
|
+
"url": "https://adserver.example/click?c=other"
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
"trackerId": "tpt_fixture_impression",
|
|
1841
|
+
"eventType": "impression",
|
|
1842
|
+
"url": "https://adserver.example/imp"
|
|
1843
|
+
}
|
|
1844
|
+
]
|
|
1845
|
+
}
|
|
1846
|
+
]
|
|
1847
|
+
},
|
|
1848
|
+
"expect": {
|
|
1849
|
+
"decodes": true
|
|
1850
|
+
},
|
|
1851
|
+
"slideTracking": {
|
|
1852
|
+
"steps": [
|
|
1853
|
+
{
|
|
1854
|
+
"slideView": 2
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
"slideClick": 2
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
"slideClick": 2
|
|
1861
|
+
}
|
|
1862
|
+
],
|
|
1863
|
+
"expect": {
|
|
1864
|
+
"beacons": [
|
|
1865
|
+
{
|
|
1866
|
+
"slide": 2,
|
|
1867
|
+
"view": "slide_view"
|
|
1868
|
+
},
|
|
1869
|
+
{
|
|
1870
|
+
"slide": 2,
|
|
1871
|
+
"click": "default"
|
|
1872
|
+
},
|
|
1873
|
+
{
|
|
1874
|
+
"slide": 2,
|
|
1875
|
+
"click": "default"
|
|
1876
|
+
}
|
|
1877
|
+
],
|
|
1878
|
+
"thirdPartyBeacons": [
|
|
1879
|
+
"tpt_fixture_click_any",
|
|
1880
|
+
"tpt_fixture_click_default",
|
|
1881
|
+
"tpt_fixture_click_any",
|
|
1882
|
+
"tpt_fixture_click_default"
|
|
1883
|
+
]
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
"id": "F20",
|
|
1889
|
+
"title": "slide views never send third-party click trackers",
|
|
1890
|
+
"fixture": {
|
|
1891
|
+
"golden": "carousel.full",
|
|
1892
|
+
"edits": [
|
|
1893
|
+
{
|
|
1894
|
+
"at": "tracking",
|
|
1895
|
+
"add": "thirdPartyTrackers",
|
|
1896
|
+
"value": [
|
|
1897
|
+
{
|
|
1898
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1899
|
+
"eventType": "click",
|
|
1900
|
+
"matchType": "any",
|
|
1901
|
+
"url": "https://adserver.example/click?c=any"
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1905
|
+
"eventType": "click",
|
|
1906
|
+
"matchType": "specific",
|
|
1907
|
+
"eventKey": "default",
|
|
1908
|
+
"url": "https://adserver.example/click?c=default"
|
|
1909
|
+
},
|
|
1910
|
+
{
|
|
1911
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1912
|
+
"eventType": "click",
|
|
1913
|
+
"matchType": "specific",
|
|
1914
|
+
"eventKey": "save_offer",
|
|
1915
|
+
"url": "https://adserver.example/click?c=other"
|
|
1916
|
+
},
|
|
1917
|
+
{
|
|
1918
|
+
"trackerId": "tpt_fixture_impression",
|
|
1919
|
+
"eventType": "impression",
|
|
1920
|
+
"url": "https://adserver.example/imp"
|
|
1921
|
+
}
|
|
1922
|
+
]
|
|
1923
|
+
}
|
|
1924
|
+
]
|
|
1925
|
+
},
|
|
1926
|
+
"expect": {
|
|
1927
|
+
"decodes": true
|
|
1928
|
+
},
|
|
1929
|
+
"slideTracking": {
|
|
1930
|
+
"steps": [
|
|
1931
|
+
{
|
|
1932
|
+
"slideView": 1
|
|
1933
|
+
},
|
|
1934
|
+
{
|
|
1935
|
+
"slideView": 2
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
"slideView": 3
|
|
1939
|
+
}
|
|
1940
|
+
],
|
|
1941
|
+
"expect": {
|
|
1942
|
+
"beacons": [
|
|
1943
|
+
{
|
|
1944
|
+
"slide": 1,
|
|
1945
|
+
"view": "slide_view"
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
"slide": 2,
|
|
1949
|
+
"view": "slide_view"
|
|
1950
|
+
},
|
|
1951
|
+
{
|
|
1952
|
+
"slide": 3,
|
|
1953
|
+
"view": "slide_view"
|
|
1954
|
+
}
|
|
1955
|
+
],
|
|
1956
|
+
"thirdPartyBeacons": []
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
},
|
|
1960
|
+
{
|
|
1961
|
+
"id": "F21",
|
|
1962
|
+
"title": "a Carousel has no creative-level click: fireClick sends nothing, so slide clicks go through the slide helper",
|
|
1963
|
+
"comment": "Publishers must not route a slide tap through fireClick (BR-SDK-03, Q9).",
|
|
1964
|
+
"fixture": {
|
|
1965
|
+
"golden": "carousel.full",
|
|
1966
|
+
"edits": [
|
|
1967
|
+
{
|
|
1968
|
+
"at": "tracking",
|
|
1969
|
+
"add": "thirdPartyTrackers",
|
|
1970
|
+
"value": [
|
|
1971
|
+
{
|
|
1972
|
+
"trackerId": "tpt_fixture_click_any",
|
|
1973
|
+
"eventType": "click",
|
|
1974
|
+
"matchType": "any",
|
|
1975
|
+
"url": "https://adserver.example/click?c=any"
|
|
1976
|
+
},
|
|
1977
|
+
{
|
|
1978
|
+
"trackerId": "tpt_fixture_click_default",
|
|
1979
|
+
"eventType": "click",
|
|
1980
|
+
"matchType": "specific",
|
|
1981
|
+
"eventKey": "default",
|
|
1982
|
+
"url": "https://adserver.example/click?c=default"
|
|
1983
|
+
},
|
|
1984
|
+
{
|
|
1985
|
+
"trackerId": "tpt_fixture_click_other",
|
|
1986
|
+
"eventType": "click",
|
|
1987
|
+
"matchType": "specific",
|
|
1988
|
+
"eventKey": "save_offer",
|
|
1989
|
+
"url": "https://adserver.example/click?c=other"
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
"trackerId": "tpt_fixture_impression",
|
|
1993
|
+
"eventType": "impression",
|
|
1994
|
+
"url": "https://adserver.example/imp"
|
|
1995
|
+
}
|
|
1996
|
+
]
|
|
1997
|
+
}
|
|
1998
|
+
]
|
|
1999
|
+
},
|
|
2000
|
+
"expect": {
|
|
2001
|
+
"decodes": true
|
|
2002
|
+
},
|
|
2003
|
+
"slideTracking": {
|
|
2004
|
+
"steps": [
|
|
2005
|
+
{
|
|
2006
|
+
"fireClick": null
|
|
2007
|
+
}
|
|
2008
|
+
],
|
|
2009
|
+
"expect": {
|
|
2010
|
+
"beacons": [],
|
|
2011
|
+
"thirdPartyBeacons": []
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
"id": "F22",
|
|
2017
|
+
"title": "fireClick with no key sends the default click of a standard",
|
|
2018
|
+
"comment": "Every standard seeds its click with key `default`, which is what fireClick sends without a key (BR-SDK-06, Q12).",
|
|
2019
|
+
"fixture": {
|
|
2020
|
+
"golden": "card.full",
|
|
2021
|
+
"edits": [
|
|
2022
|
+
{
|
|
2023
|
+
"at": "tracking",
|
|
2024
|
+
"add": "thirdPartyTrackers",
|
|
2025
|
+
"value": [
|
|
2026
|
+
{
|
|
2027
|
+
"trackerId": "tpt_fixture_click_any",
|
|
2028
|
+
"eventType": "click",
|
|
2029
|
+
"matchType": "any",
|
|
2030
|
+
"url": "https://adserver.example/click?c=any"
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
"trackerId": "tpt_fixture_click_default",
|
|
2034
|
+
"eventType": "click",
|
|
2035
|
+
"matchType": "specific",
|
|
2036
|
+
"eventKey": "default",
|
|
2037
|
+
"url": "https://adserver.example/click?c=default"
|
|
2038
|
+
},
|
|
2039
|
+
{
|
|
2040
|
+
"trackerId": "tpt_fixture_click_other",
|
|
2041
|
+
"eventType": "click",
|
|
2042
|
+
"matchType": "specific",
|
|
2043
|
+
"eventKey": "save_offer",
|
|
2044
|
+
"url": "https://adserver.example/click?c=other"
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
"trackerId": "tpt_fixture_impression",
|
|
2048
|
+
"eventType": "impression",
|
|
2049
|
+
"url": "https://adserver.example/imp"
|
|
2050
|
+
}
|
|
2051
|
+
]
|
|
2052
|
+
}
|
|
2053
|
+
]
|
|
2054
|
+
},
|
|
2055
|
+
"expect": {
|
|
2056
|
+
"decodes": true
|
|
2057
|
+
},
|
|
2058
|
+
"slideTracking": {
|
|
2059
|
+
"steps": [
|
|
2060
|
+
{
|
|
2061
|
+
"fireClick": null
|
|
2062
|
+
}
|
|
2063
|
+
],
|
|
2064
|
+
"expect": {
|
|
2065
|
+
"beacons": [
|
|
2066
|
+
{
|
|
2067
|
+
"click": "default"
|
|
2068
|
+
}
|
|
2069
|
+
],
|
|
2070
|
+
"thirdPartyBeacons": [
|
|
2071
|
+
"tpt_fixture_click_any",
|
|
2072
|
+
"tpt_fixture_click_default"
|
|
2073
|
+
]
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
"id": "F23",
|
|
2079
|
+
"title": "expand and close are sent verbatim as custom events and are not clicks",
|
|
2080
|
+
"comment": "The publisher calls them when the banner actually expands or closes; no click is sent and no third-party click tracker fires (BR-SDK-07).",
|
|
2081
|
+
"fixture": {
|
|
2082
|
+
"golden": "expandable_banner.full",
|
|
2083
|
+
"edits": [
|
|
2084
|
+
{
|
|
2085
|
+
"at": "tracking",
|
|
2086
|
+
"add": "thirdPartyTrackers",
|
|
2087
|
+
"value": [
|
|
2088
|
+
{
|
|
2089
|
+
"trackerId": "tpt_fixture_click_any",
|
|
2090
|
+
"eventType": "click",
|
|
2091
|
+
"matchType": "any",
|
|
2092
|
+
"url": "https://adserver.example/click?c=any"
|
|
2093
|
+
},
|
|
2094
|
+
{
|
|
2095
|
+
"trackerId": "tpt_fixture_click_default",
|
|
2096
|
+
"eventType": "click",
|
|
2097
|
+
"matchType": "specific",
|
|
2098
|
+
"eventKey": "default",
|
|
2099
|
+
"url": "https://adserver.example/click?c=default"
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
"trackerId": "tpt_fixture_click_other",
|
|
2103
|
+
"eventType": "click",
|
|
2104
|
+
"matchType": "specific",
|
|
2105
|
+
"eventKey": "save_offer",
|
|
2106
|
+
"url": "https://adserver.example/click?c=other"
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
2109
|
+
"trackerId": "tpt_fixture_impression",
|
|
2110
|
+
"eventType": "impression",
|
|
2111
|
+
"url": "https://adserver.example/imp"
|
|
2112
|
+
}
|
|
2113
|
+
]
|
|
2114
|
+
}
|
|
2115
|
+
]
|
|
2116
|
+
},
|
|
2117
|
+
"expect": {
|
|
2118
|
+
"decodes": true
|
|
2119
|
+
},
|
|
2120
|
+
"slideTracking": {
|
|
2121
|
+
"steps": [
|
|
2122
|
+
{
|
|
2123
|
+
"custom": "expand"
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
"custom": "close"
|
|
2127
|
+
}
|
|
2128
|
+
],
|
|
2129
|
+
"expect": {
|
|
2130
|
+
"beacons": [
|
|
2131
|
+
{
|
|
2132
|
+
"custom": "expand"
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
"custom": "close"
|
|
2136
|
+
}
|
|
2137
|
+
],
|
|
2138
|
+
"thirdPartyBeacons": []
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
"id": "F24",
|
|
2144
|
+
"title": "an asset tap is sent verbatim as a custom event and is not a click",
|
|
2145
|
+
"comment": "BR-SDK-07.",
|
|
2146
|
+
"fixture": {
|
|
2147
|
+
"golden": "branded_assets.full",
|
|
2148
|
+
"edits": [
|
|
2149
|
+
{
|
|
2150
|
+
"at": "tracking",
|
|
2151
|
+
"add": "thirdPartyTrackers",
|
|
2152
|
+
"value": [
|
|
2153
|
+
{
|
|
2154
|
+
"trackerId": "tpt_fixture_click_any",
|
|
2155
|
+
"eventType": "click",
|
|
2156
|
+
"matchType": "any",
|
|
2157
|
+
"url": "https://adserver.example/click?c=any"
|
|
2158
|
+
},
|
|
2159
|
+
{
|
|
2160
|
+
"trackerId": "tpt_fixture_click_default",
|
|
2161
|
+
"eventType": "click",
|
|
2162
|
+
"matchType": "specific",
|
|
2163
|
+
"eventKey": "default",
|
|
2164
|
+
"url": "https://adserver.example/click?c=default"
|
|
2165
|
+
},
|
|
2166
|
+
{
|
|
2167
|
+
"trackerId": "tpt_fixture_click_other",
|
|
2168
|
+
"eventType": "click",
|
|
2169
|
+
"matchType": "specific",
|
|
2170
|
+
"eventKey": "save_offer",
|
|
2171
|
+
"url": "https://adserver.example/click?c=other"
|
|
2172
|
+
},
|
|
2173
|
+
{
|
|
2174
|
+
"trackerId": "tpt_fixture_impression",
|
|
2175
|
+
"eventType": "impression",
|
|
2176
|
+
"url": "https://adserver.example/imp"
|
|
2177
|
+
}
|
|
2178
|
+
]
|
|
2179
|
+
}
|
|
2180
|
+
]
|
|
2181
|
+
},
|
|
2182
|
+
"expect": {
|
|
2183
|
+
"decodes": true
|
|
2184
|
+
},
|
|
2185
|
+
"slideTracking": {
|
|
2186
|
+
"steps": [
|
|
2187
|
+
{
|
|
2188
|
+
"custom": "asset_tap"
|
|
2189
|
+
}
|
|
2190
|
+
],
|
|
2191
|
+
"expect": {
|
|
2192
|
+
"beacons": [
|
|
2193
|
+
{
|
|
2194
|
+
"custom": "asset_tap"
|
|
2195
|
+
}
|
|
2196
|
+
],
|
|
2197
|
+
"thirdPartyBeacons": []
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
},
|
|
2201
|
+
{
|
|
2202
|
+
"id": "F25",
|
|
2203
|
+
"title": "a Standard Video without a destination sends no click",
|
|
2204
|
+
"comment": "No destination means no click action and no click tracker (BR-SDK-08).",
|
|
2205
|
+
"fixture": {
|
|
2206
|
+
"golden": "standard_video.minimal"
|
|
2207
|
+
},
|
|
2208
|
+
"expect": {
|
|
2209
|
+
"decodes": true
|
|
2210
|
+
},
|
|
2211
|
+
"slideTracking": {
|
|
2212
|
+
"steps": [
|
|
2213
|
+
{
|
|
2214
|
+
"fireClick": null
|
|
2215
|
+
}
|
|
2216
|
+
],
|
|
2217
|
+
"expect": {
|
|
2218
|
+
"beacons": [],
|
|
2219
|
+
"thirdPartyBeacons": []
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
1594
2222
|
}
|
|
1595
2223
|
]
|
|
1596
2224
|
}
|