├── Baby-SHARC.md ├── LICENSE ├── README.md ├── contributing.md ├── messaging_protocol.md └── sharc ├── README.md ├── SHARC.zip ├── creatives ├── video-creative.html └── video-creative.js ├── favicon.ico ├── sharc-lifecycle.png ├── sharc-protocol.js ├── styles.css ├── template.html └── template.js /Baby-SHARC.md: -------------------------------------------------------------------------------- 1 | 2 | Please review the IAB Tech Lab Open Source Initiative Governance guidelines [here](http://iabtechlab.com/opensource) for contributing to this project. 3 | 4 | # Welcome to the SHARC project! 5 | SHARC is an acronym for Safe HTML Ad Rich-media Container. Our goal is to design, develop, and maintain an API that manages an ad container that works cross-platform. 6 | 7 | *Our Motto:* 8 | Write one ad; serve it anywhere! 9 | 10 | ## Baby SHARC, doo do doo do 11 | SHARC is born of two previous IAB Tech Lab standards: [SafeFrame](https://iabtechlab.com/standards/safeframe-implementation-guidelines/) and [MRAID](https://iabtechlab.com/standards/mobile-rich-media-ad-interface-definitions-mraid/) (Mobile Richmedia Ad Interface Definition). SafeFrame was designed to work in web and MRAID was designed to work in-app on mobile devices. Designing an ad for a cross-platform campaign meant designing at least two different ads to work with two different standards. Besides the lack of cross-platform compatibility, each standard had its limitations for control and performance. 12 | 13 | One complaint from consumers on ads is having a bad ad experience, such as [an ad that plays audio](https://www.youtube.com/watch?v=BhmRvUjJFh4&ab_channel=PrincessThandeka) when it’s not supposed to or an ad that won’t close when it’s supposed to. Complaints from advertisers and ad developers is a lack of clarity around which controls to provide and how to control them. For example, in some cases the ad supplies a close button while in others, the publisher provides a close button. And whether one or both close buttons are provided, neither operator may know that a consumer wants to close the ad or who should execute the close. Complaints from publishers include a lack of clear definition between ad content and page content. Publishers need to protect their pages or apps from potentially harmful ads, whether it’s just a badly designed ad or an intentionally malicious ad. Because of this lack of clarity in execution, troubleshooting and reporting can be time consuming. 14 | 15 | ## Fish are friends, not food! 16 | Our aim for this project is to take the best of both SafeFrame and MRAID worlds and create an ad container that provides seamless abilities to interact with an ad—no matter where it’s served. Ad developers should know exactly what controls to provide and the expected result for real time execution. Publishers should be able to clearly delineate page content from ad content with ultimate control over protecting their pages and apps from broken or malicious ads. 17 | 18 | Transparency for all parties, a clean and seamless rich ad experience that just works, and the ability to write one ad that can be served anywhere will save everyone a lot of headache and frustration. 19 | 20 | ## Join us! 21 | To bring SHARC to life, we need your help. SHARC is in the beginning phase of development. As of July 2021, we’re working on a proof of concept based on some initial use cases and requirements. As part of the IAB Open Source initiative, anyone can participate. Email [Katie Stroud](mailto:katie@iabtechlab.com) with any questions or to get more information. 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | Copyright 2021 IAB Technology Laboratory, Inc 179 | 180 | Licensed under the Apache License, Version 2.0 (the "License"); 181 | you may not use this file except in compliance with the License. 182 | You may obtain a copy of the License at 183 | 184 | http://www.apache.org/licenses/LICENSE-2.0 185 | 186 | Unless required by applicable law or agreed to in writing, software 187 | distributed under the License is distributed on an "AS IS" BASIS, 188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 189 | See the License for the specific language governing permissions and 190 | limitations under the License. 191 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Secure HTML Ad Richmedia Container (SHARC) Product Specification

2 | 3 | 4 |

Overview

5 | 6 | 7 | Secure HTML Ad Richmedia Container (SHARC) is a secure container API for managed communication between an app webview or webpage and a served ad creative. 8 | 9 |

Updates

10 | 11 | 12 | 13 | 14 | 15 | 17 | 19 | 20 | 21 | 23 | 25 | 26 | 27 | 29 | 31 | 32 |
Version 16 | Summary 18 |
1st draft 22 | Initial release to public comment 24 |
Product Requirements Doc (PRD) 28 | First full product specification released to public for development. Changes from initial draft include a simplified workflow, cleaner use of extensions (supported features), and general edits throughout. 30 |
33 | 34 | 35 |

Contributing Members

36 | 37 | 38 | Co-chairs on this project: 39 | 40 | 41 | 42 | * Jeffrey Carlson, Chartboost 43 | * Aron Schatz, DoubleVerify 44 | 45 | Other key contributors: 46 | 47 | 48 | 49 | * Kyle Grymonprez, Chartboost 50 | * Marian Rusnak, Verizon 51 | * Bichen Wang, Chartboost 52 | * Laura Evans, Flashtalking by Media Ocean 53 | * Sarah Kirtcheff, Flashtalking by Media Ocean 54 | 55 |

Table of Contents

56 | 57 | 58 | 59 | [TOC] 60 | 61 | 62 |

Audience

63 | 64 | 65 | Developers on the sell side for content platforms will need the details in this document for implementing SHARC on their systems. On the buy side, creative developers will need this document to develop display ads that make use of the SHARC APIs. 66 | 67 |

About IAB Tech Lab

68 | 69 | 70 | The IAB Technology Laboratory (Tech Lab) is a non-profit consortium that engages a member community globally to develop foundational technology and standards that enable growth and trust in the digital media ecosystem. Composed of digital publishers, ad technology firms, agencies, marketers, and other member companies, IAB Tech Lab focuses on improving the digital advertising supply chain, measurement, and consumer experiences, while promoting responsible use of data. Its work includes the OpenRTB real-time bidding protocol, ads.txt anti- fraud specification, Open Measurement SDK for viewability and verification, VAST video specification, and DigiTrust identity service. Board members include ExtremeReach, Facebook, Google, GroupM, Hearst Digital Media, Index Exchange, Integral Ad Science, LinkedIn, LiveRamp, MediaMath, Microsoft, Oracle Data Cloud, Pandora, PubMatic, Quantcast, Rakuten Marketing, Telaria, The Trade Desk, Verizon Media Group, Xandr, and Yahoo! Japan. Established in 2014, the IAB Tech Lab is headquartered in New York City with staff in San Francisco, Seattle, and London. Learn more at https://www.iabtechlab.com. 71 | 72 |

Introduction

73 | 74 | 75 | Secure HTML Ad Richmedia Container (SHARC) is a secure container API for managed communication between an app or webpage and a served ad creative. 76 | 77 | SHARC is built on the same premise as two of IAB Tech Lab’s ad container standards: SafeFrame and Mobile Rich Ad Interface Definition (MRAID). SafeFrame was designed to run in-web and MRAID was designed to run in a webview in mobile in-app devices. The trouble with these two standards is that they’re both very similar and yet different enough that you would have to build two different ad creatives to run a campaign across both web and mobile. 78 | 79 | Several ad platforms have tried to build a bridge between the two APIs so that an MRAID ad could also run in a SafeFrame container and a SafeFrame ad could run in an MRAID container. Unfortunately, the differences are stark enough that these attempts at cross-compatibility never really worked out. 80 | 81 | The Safe Ad Container working group for ad experiences at IAB Tech Lab have started from the ground up to build a standard for managing rich interactive display ads. Our motto for SHARC is: 82 | 83 | _Build one ad; serve it everywhere._ 84 | 85 | With SHARC, a creative developer can build one ad with all the available API functions and serve it to any connected display platform that has implemented SHARC. This is not just limited to web or mobile in-app, it includes a variety of platforms (such as CTV) that are available today and future platforms. 86 | 87 |

Guiding principles

88 | 89 | 90 | 91 | 92 | * Performance 93 | * Industry standards interoperability 94 | * Consumer protection 95 | * Publisher safety and security 96 | * Low barrier of entry (simplicity and ubiquity) 97 | * Minimize impact on key stakeholders in the supply chain (example: OMID included JS libraries to reduce customization that impacted efficiency) 98 | * No ambiguity (detailed specifics in both spec and implementation guide) - while also not delaying release for the sake of clarifying, sub-groups to focus on blocking issues and defying a process to get things done 99 | * Extensibility (helps enable testing of new features before implementing) 100 | * Graceful degradation 101 | 102 |

Scope

103 | 104 | 105 | SHARC is intended for managing rich media ad interactions in display placements. While video can be included in the final creative, SHARC provides no playback controls or tracking. SHARC ads can also be served into video players that have implemented SHARC and may be a great way to handle non-linear and companion ads in video ad placements, but this spec does not yet cover that use case. 106 | 107 |

Out of Scope

108 | 109 | 110 | The following ad tech operations are out of scope in SHARC: 111 | 112 | 113 | 114 | * Ad request 115 | * Ad delivery 116 | * Measurement 117 | * Ad tracking and reports 118 | 119 | While the above operations are out of scope for SHARC, they play a role in the success of SHARC, and certain SHARC functions either use or support these operations. 120 | 121 | For example IAB Tech Lab’s Advertising Common Object Model (AdCOM) is a standardized data structure for relaying details about the placement, the creative, the context, and any other information that all parties in the supply chain need for placing, tracking, and reporting on the ad exchanges in the campaigns they run. It is a dataspec used in the ad request and response, and SHARC requires data from the same dataspec to communicate some of these unchanging details as part of the initiation cycle. AdCOM is the default and preferred dataspec to use, but SHARC itself doesn’t supply any of this data; it only provides additional data expected to change during runtime, such as the current state of the container, size changes, or volume details. 122 | 123 | The example above explains how other ad operations beyond loading and managing interactions are left to other standards, thereby simplifying SHARC as much as possible. This separation helps SHARC meet some of its guiding principles such as performance and interoperability. 124 | 125 |

Goals

126 | 127 | 128 | _Write one ad; serve it anywhere._ 129 | 130 | This is the key goal of SHARC. In order to achieve this goal, we must achieve certain supporting goals to integrate SHARC into systems and operations that make up the digital advertising supply chain. 131 | 132 | Adoption is dependent on the following: 133 | 134 | 135 | 136 | * Producing a clear and unambiguous spec for SHARC implementers (this document) 137 | * Providing guidance for different operational audiences targeted to their specific needs for making use of SHARC 138 | * Developing reference code, tools, and examples that simplify implementation 139 | * Creating an awareness of the challenges that SHARC solves in the marketplace for display advertising, especially where no solution currently exists 140 | * Educating different audiences on the benefits and use of SHARC 141 | * Regular updates to support growing market needs 142 | 143 | If you would like to get involved, please reach out to [support@iabtechlab.com](mailto:support@iabtechlab.com) and we’ll set you up. You can also visit our GitHub repository at [https://github.com/IABTechLab/SHARC](https://github.com/IABTechLab/SHARC). 144 | 145 |

How it works

146 | 147 | 148 | SHARC is a protocol for managing ad interactions in a secure container that prevents an ad from accessing data on the platform where the ad displays. In the most simplistic overview of how it works, the steps are as follows: 149 | 150 | 151 | 152 | * [pre-SHARC] an ad is matched and delivered to the SHARC placement 153 | * SHARC initiates. In this step, the following occurs: 154 | * The SHARC-enabled platform creates the secure container (for example: an iframe on web, webview on mobile). 155 | * The SHARC container inserts the creative markup and the creative prepares its resources. 156 | * Once in a state to receive SHARC information, the creative informs the container that it is ready to receive initialization information. 157 | * The SHARC container initializes and provides the creative with data about the container. 158 | * Data about the environment (placement) and the creative is pulled from the dataspec (default is AdCOM) along with any runtime details such as current size and state and volume settings. 159 | * Once the creative and the container are ready, SHARC asks the creative to start and waits for the creative to respond. 160 | * Creative responds with “resolve” indicating that it is ready 161 | * Creative executes, using SHARC functions to resize, navigate away from platform, close, etc. 162 | * Upon completion of the ad experience, SHARC signals a close function and unloads the ad. 163 | 164 | A diagram and more detailed descriptions of different use cases are provided in the section on [Common Workflows](#common-workflows). 165 | 166 |

The relationship between SIMID and SHARC

167 | 168 | 169 | To develop SHARC, we looked to the structure of SIMID as a model. SIMID is IAB Tech Lab’s Secure Interactive Media Interface Definition. Like SHARC, it uses a secure container to manage an ad experience, except that SIMID functions in the context of a media player. Discussion on whether SIMID should be extended to also handle display ads across platforms or to develop a new standard (SHARC) to handle display ads separately from the SIMID video standard was explored. The decision to create a separate standard emerged as part of the following logic. 170 | 171 | As API specs and standards at IAB Tech Lab evolve, there is an opportunity to develop new APIs with shared design principles of existing APIs. Doing so creates a firm foundation upon which new APIs can be built more rapidly while lowering the learning curve for the industry to adopt new specs. 172 | 173 | SHARC has opted to share the same messaging protocol and API structure that SIMID developed in order to take full advantage of this opportunity. Sharing this core messaging structure has enabled SHARC to more rapidly prototype a spec tasked with being the cross-platform rich media successor to the Safe Frame and MRAID specs. 174 | 175 | In adopting a lot of the API design, features and functionality, a common question asked is why shouldn’t SIMID solve all use cases? 176 | 177 | The three main reasons are specialization, flexibility and simplicity. 178 | 179 | 180 | 181 | 1. For specialization, SIMID was created exclusively to provide rich interactivity for streaming audio and video ads. Expanding its scope beyond its intended use case is exactly how its predecessor VPAID got into trouble. SHARC being separated as a rich media container resolves any issues with SIMID becoming overloaded. 182 | 2. For flexibility, it allows both SIMID and SHARC to develop separately as market innovations, needs and problems to be solved potentially fork former shared priorities. 183 | 3. For simplicity, SIMID and SHARC can keep a focused API spec relevant to each solution. SHARC has no parallel use case for certain video functions, for example. These improvements can be updated independently without forcing unnecessary version updates on technology stacks. 184 | 185 | It is important to have different tools for different use cases. Use SIMID when working with VAST audio or video creative that need interactivity. Use SHARC when working with next-gen rich media display HTML5 creative in web and other platforms. A use case for both specs could be a VAST creative with interactivity and a companion ad as an end card. SIMID would be used to overlay the video and SHARC would be used to display the companion end card. 186 | 187 |

Secure By Default

188 | 189 | 190 | One of the main tenets of SHARC is the focus on providing a robust and secure communication and security framework for rich media ad experiences. The end result is that the container performs almost all the functions needed for interacting with the greater publisher content (a web page or an application). The creative must request for actions to be done on the container and the container will either resolve or reject those requests. This puts the container in control and allows for publishers to enable their expected consumer experience without an ad taking over their content. There are common uses cases covered to allow for the wide range of ad experience, but this standard ensures that an ad cannot present a poor consumer experience without the consent of the container. 191 | 192 |

Terminology

193 | 194 | 195 | **Device** - The physical device such as a computer, a phone, or a tablet. 196 | 197 | **Platform** - The operating system (OS) or windowing manager such MacOS, iOS, Android, or KDE 198 | 199 | \ 200 | **Host** - Window/App main content rendering area 201 | 202 | **Publisher Content** - The Document interface that represents any web page loaded in a browser or web app and serves as an entry point into the web page's content. 203 | 204 | **Viewport** - The part of the publisher content that is visible to the user. The browser's [viewport](https://developer.mozilla.org/en-US/docs/Glossary/Viewport) is the area of the window in which web content can be seen. This is often not the same size as the rendered page, in which case the browser provides scrollbars for the user to scroll around and access all the content. 205 | 206 | **Container **- An object, such as an iframe or webview, that implements the SHARC API and is capable of rendering HTML. 207 | 208 | **Container Viewport** - The part of the creative HTML that is displayed in the container. 209 | 210 | **Displayed** - HTML content that exists in a container and is within the container viewport. This does not mean that the HTML content is visible, though. 211 | 212 | **Navigation Event** - The call for navigation to a URL triggered in the ad creative. This action opens a new app or page, effectively abandoning the content in which the ad was being executed. 213 | 214 | **Interaction Event** - An action that is handled inside of a creative. 215 | 216 | **Render vs Render on screen** 217 | 218 | **API - **Application Programming Interface 219 | 220 |

API Reference

221 | 222 | 223 | SHARC is a set of messages and data structures that ad-rendering parties exchange using a messaging protocol. 224 | 225 |

Reference Table: Container

226 | 227 | 228 | 229 | 230 | 231 | 233 | 235 | 237 | 238 | 239 | 241 | 243 | 245 | 246 | 247 | 249 | 251 | 253 | 254 | 255 | 257 | 259 | 261 | 262 | 263 | 265 | 267 | 269 | 270 | 271 | 273 | 275 | 277 | 278 | 279 | 281 | 283 | 285 | 286 | 287 | 289 | 291 | 293 | 294 |
API 232 | resolve 234 | reject 236 |
SHARC:Container:init 240 | resolve 242 | reject 244 |
SHARC:Container:startCreative 248 | resolve 250 | reject 252 |
SHARC:Container:stateChange 256 | n/a 258 | n/a 260 |
SHARC:Container:placementChange 264 | n/a 266 | n/a 268 |
SHARC:Container:log 272 | n/a 274 | n/a 276 |
SHARC:Container:fatalError 280 | resolve 282 | n/a 284 |
SHARC:Container:close 288 | resolve 290 | n/a 292 |
295 | 296 | 297 |

Reference Table: Creative

298 | 299 | 300 | 301 | 302 | 303 | 305 | 307 | 309 | 310 | 311 | 313 | 315 | 317 | 318 | 319 | 321 | 323 | 325 | 326 | 327 | 329 | 331 | 333 | 334 | 335 | 337 | 339 | 341 | 342 | 343 | 345 | 347 | 349 | 350 | 351 | 353 | 355 | 357 | 358 | 359 | 361 | 363 | 365 | 366 | 367 | 369 | 371 | 373 | 374 | 375 | 377 | 379 | 381 | 382 | 383 | 385 | 387 | 389 | 390 | 391 | 393 | 395 | 397 | 398 |
API 304 | resolve 306 | reject 308 |
SHARC:Creative:createSession 312 | n/a 314 | n/a 316 |
SHARC:Creative:fatalError 320 | n/a 322 | n/a 324 |
SHARC:Creative:getContainerState 328 | resolve 330 | n/a 332 |
SHARC:Creative:getPlacementOptions 336 | resolve 338 | n/a 340 |
SHARC:Creative:log 344 | n/a 346 | n/a 348 |
SHARC:Creative:reportInteraction 352 | resolve 354 | n/a 356 |
SHARC:Creative:requestNavigation 360 | n/a 362 | n/a 364 |
SHARC:Creative:requestPlacementChange 368 | resolve 370 | n/a 372 |
SHARC:Creative:requestClose 376 | resolve 378 | n/a 380 |
SHARC:Creative:getFeatures 384 | resolve 386 | reject 388 |
SHARC:Creative:request[FeatureName] 392 | resolve 394 | reject 396 |
399 | 400 | 401 |

Messages from the Container

402 | 403 | 404 | SHARC specifies a group of messages that enables the container to transmit data, instructions, or state changes to the creative. The container prepends such message types with the `SHARC:Container` namespace. The container can push any messages onto the message bus using extensions. Any of the parties interacting with SHARC can read these messages as long as they are familiar with the extension(s). 405 | 406 | 407 | `SHARC:Container` messages do not communicate ad creative states; SHARC dedicates Messages Triggered by Creative Events to report creative status. A private message bus can be created to inform internal systems on messages sent by the creative, or a public message bus can be created to share these messages to other systems, such as measurement providers. 408 | 409 | While some `SHARC:Container` messages expect `resolve` and/or `reject` creative responses, other messages do not require replies. 410 | 411 |

SHARC:Container:init

412 | 413 | 414 | 415 | The purpose of the `SHARC:Container:init` message is to relay information to the creative and prepare for the creative to start the SHARC ad experience. See [Typical Initialization WorkFlow](#typical-initialization-workflow). 416 | 417 | 418 | The creative must respond to `Container:init` with either [resolve](#resolve) or [reject](#reject). 419 | 420 | 421 | ``` 422 | dictionary MessageArgs { 423 | required EnvironmentData environmentData; 424 | Features supportedFeatures; 425 | }; 426 | environmentData, 427 | Information about publisher's environment and container capacities upon initialization. 428 | supportedFeatures, 429 | Information about features supported beyond basic functionality. Features that SHARC supports use the namespace com.iabtechlab.sharc.[featureName]. 430 | Other third party features will use a separate namespace. 431 | ``` 432 | 433 | 434 | 435 | ``` 436 | dictionary EnvironmentData { 437 | required Placement currentPlacement; 438 | required Dataspec dataspec; 439 | required Data data; 440 | Navigation containerNavigation; 441 | required enum currentState; 442 | required string version; 443 | boolean isMuted; 444 | float volume; 445 | }; 446 | 447 | currentPlacement, 448 | Information about the container's current placement properties such as dimensions, location, inline or over content, etc. 449 | dataspec, 450 | The name and version of the dataspec that provides placement and creative information. Default dataspec is AdCOM. 451 | data, 452 | The data provided by the dataspec identified. 453 | containerNavigation, 454 | Information about how the container handles navigation. The container always handles navigation except in situations where it's not possible such is in a browser. The creative must always request navigation regardless of environment so that the container can log the instance, even if it cannot handle the navigation request. 455 | currentState, 456 | The current state of the container: ready, active, passive, hidden, frozen, closing, unloaded. See table for descriptions under SHARC:Container:stateChange. 457 | version, 458 | The full version number of the SHARC implementation. 459 | isMuted, 460 | True if known and device is muted. 461 | volume, 462 | If known, the volume level of the device, expressed as a number between 0 and 1.0. Value is -1 if unknown. 463 | ``` 464 | 465 | 466 | 467 | ``` 468 | dictionary Feature { 469 | string name; 470 | version version; 471 | object functions; 472 | 473 | }; 474 | 475 | name, 476 | The name of the feature. Features that SHARC supports use the namespace com.iabtechlab.sharc.[featureName]. Third party features will use a separate namespace. 477 | version, 478 | The version of the named feature. 479 | functions, 480 | An object array describing the available functions of the named feature. 481 | ``` 482 | 483 | 484 | 485 | ``` 486 | dictionary Placement { 487 | 488 | required Dimensions initialDefaultSize, 489 | required Dimensions minDefaultSize, 490 | required Dimensions maxDefaultSize, 491 | required Dimensions maxExpandSize, 492 | required Dimensions viewportSize 493 | }; 494 | 495 | initialDefaultSize 496 | The initial dimensions of the container at the time that startCreative is called.. 497 | minDefaultSize 498 | The minimum dimensions that the container can be in the default placement (without a request to change the placement size). If equal to initialDefaultSize, placement size cannot be smaller than default. 499 | maxDefaultSize 500 | The maximum dimensions that the container can be in the default placement (without a request to change the placement size). If equal to initialDefaultSize, placement size cannot be larger than default. 501 | viewportSize 502 | The maximum dimensions of the window or viewport that the container is aware of. Likely, this is the screen size. 503 | ``` 504 | 505 | 506 | 507 | ``` 508 | dictionary Dimensions { 509 | required long width; 510 | required long height; 511 | }; 512 | 513 | width, 514 | The width of the container in density-independent pixels (DIPS) 515 | height, 516 | The height of the container in density-independent pixels (DIPS) 517 | ``` 518 | 519 | 520 | 521 | ``` 522 | dictionary Dataspec { 523 | required string model; 524 | required string ver; 525 | }; 526 | 527 | model, 528 | The data structure model used to provide data. Default is AdCOM. 529 | ver, 530 | The version of the data model identified above. Default is "1.0". 531 | ``` 532 | 533 | 534 | 535 | ``` 536 | dictionary Data { 537 | // Defined by the dataspec 538 | }; 539 | AdCOM example 540 | 541 | dictionary Data { 542 | required AdcomAd ad; 543 | required AdcomPlacement placement 544 | required AdcomContext context 545 | }; 546 | 547 | data, 548 | The data provided by the dataspec identified. Recommended AdCOM nodes: 549 | ad (see AdCOM Ad Object) 550 | placement (see AdCOM Placement Object) 551 | context (see AdCOM Context Object) 552 | 553 | ``` 554 | 555 | 556 | 557 | ``` 558 | dictionary Navigation { 559 | boolean navigationPossible; 560 | boolean navigationAllowed; 561 | }; 562 | 563 | navigationPossible, 564 | True if the platform in which the container operates supports navigation away from the ad experience and can be handled by the container. If false, navigation away from the ad experience must be handled by the creative (if possible); however, the creative must still always request navigation so that the container can log the request. 565 | navigationAllowed, 566 | True if navigationPossible=true and container allows navigation away from the ad experience. 567 | 568 | ``` 569 | 570 | 571 |
572 | _resolve_
573 | 574 | 575 | The creative acknowledges the initialization parameters. 576 | 577 | 578 | If the creative delays calling resolve, see [Creative Delays Resolving Init](#creative-delays-resolving-init) 579 | 580 |
581 | _reject_
582 | 583 | 584 | The creative may respond with a reject based on its internal logic. 585 | 586 | 587 | ``` 588 | dictionary MessageArgs 589 | { 590 | required unsigned short errorCode; 591 | DOMString reason; 592 | }; 593 | 594 | errorCode, 595 | See Error Codes. 596 | reason, 597 | Optional information about cause of rejection. 598 | ``` 599 | 600 | 601 | The container then will follow the rejection workflow. See [Creative Rejects Init](#creative-delays-resolving-init). 602 | 603 |

SHARC:Container:startCreative

604 | 605 | 606 | See [Typical Initialization Workflow](#typical-initialization-workflow) 607 | 608 | The container posts `SHARC:Container:startCreative` message when it is ready to make the iframe visible. The container waits for a `resolve` response to display itself. The interactive creative should be ready to reply to `Container:startCreative` immediately. 609 | 610 | [SHARC:Container:init](#sharc-container-init) section describes the flow that precedes the instant the container emits a `Container:startCreative` message. 611 | 612 |
_resolve_
613 | 614 | 615 | By posting `resolve`, the interactive creative acknowledges that it is ready for display. The creative should be ready to respond immediately. The container makes itself visible upon a resolve receipt 616 | 617 | Refer to [Typical Initialization WorkFlow](#typical-initialization-workflow). 618 | 619 |
_reject_
620 | 621 | 622 | When the creative responds with a reject, the container may unload the ad. The player reports an error tracker with the `errorCode` the creative supplied. 623 | 624 | 625 | ``` 626 | dictionary MessageArgs{ 627 | required unsigned short errorCode; 628 | DOMString reason; 629 | }; 630 | 631 | errorCode, 632 | See Error Codes. 633 | reason, 634 | Additional information. 635 | ``` 636 | 637 | 638 |

SHARC:Container:stateChange

639 | 640 | 641 | The container posts a SHARC:Container:stateChange message whenever the container state is changed. Certain container or environment events can trigger a state change. For example, Container:init triggers the “ready” state. Or a change in focus, such as when a user switches tabs in a browser, can change the state from “active” or “passive” to “hidden.” The new container state is reported with the message. 642 | 643 | 644 | ``` 645 | dictionary MessageArgs{ 646 | DOMString containerState; 647 | }; 648 | 649 | containerState, 650 | The current (new) container state, which is one of: created, ready, active, inactive, closing, destroyed. See reference chart below for definitions of states. 651 | 652 | ``` 653 | 654 | 655 |

Table of possible container states

656 | 657 | 658 | 659 | 660 |

>>>>> gd2md-html alert: inline image link here (to images/image1.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

661 | 662 | 663 | ![alt_text](images/image1.png "image_tooltip") 664 | 665 | 666 | 667 | 668 | 669 | 671 | 673 | 674 | 675 | 677 | 691 | 692 | 693 | 695 | 705 | 706 | 707 | 709 | 723 | 724 | 725 | 727 | 739 | 740 | 741 | 743 | 755 | 756 | 757 | 759 | 771 | 772 |
State 670 | Description 672 |
created 676 | The container has created the container but has not yet initialized the container. The creative may or may not have started the session yet. 678 |

679 | Possible previous states: 680 |

681 | (none) 682 |

683 | Possible next states: 684 |

685 | active 686 |

687 | destroyed (if the start session times out or some other error occurs) 688 |

689 | Note: This event is not be queryable by the creative but represents a state of SHARC before the container and creative handshake is ready for bidirectional communication. 690 |

ready 694 | The container has successfully completed initialization (Container:init) and is ready for the creative to start. 696 |

697 | Possible previous states: 698 |

699 | created 700 |

701 | Possible next states: 702 |

703 | active 704 |

active 708 | Container is currently in a space that is visible and in use (has focus and input) 710 |

711 | Possible previous states: 712 |

713 | ready (Container:init) 714 |

715 | inactive 716 |

717 | Possible next states: 718 |

719 | inactive 720 |

721 | closing 722 |

inactive 726 | Container is currently in a space that is visible but no longer in use (has focus but no input). 728 |

729 | Possible previous states: 730 |

731 | active 732 |

733 | Possible next states: 734 |

735 | active 736 |

737 | closing 738 |

closing 742 | The close sequence has been initiated and the container is in a state of closing. 744 |

745 | Possible previous states: 746 |

747 | active 748 |

749 | inactive 750 |

751 | Possible next states: 752 |

753 | destroyed 754 |

destroyed 758 | The container has unloaded and can no longer function. 760 |

761 | Possible previous states: 762 |

763 | closing 764 |

765 | Possible next states: 766 |

767 | (none) 768 |

769 | Note: This event is not be queryable by the creative but represents a state of SHARC after the container and creative handshake has ended and no bidirectional communication is possible anymore. 770 |

773 | 774 | 775 | The creative can request the current state of the container any time using [Creative:getContainerState](#sharc-creative-getcontainerstate). 776 | 777 |

SHARC:Container:placementChange

778 | 779 | 780 | When the container changes its properties, such as dimensions and location (usually in response to a request by the creative), it posts the `SHARC:Container:placementChange` message. The message describes the container dimensions and coordinates. 781 | 782 | 783 | ``` 784 | dictionary MessageArgs{ 785 | required Placement placementUpdate; 786 | }; 787 | 788 | placementUpdate, 789 | Information about changes in the container properties, such as dimensions and location. 790 | ``` 791 | 792 | 793 | 794 | ``` 795 | dictionary Placement { 796 | Dimensions containerDimensions; 797 | boolean inline; 798 | enum standardSize; 799 | array dynamicFeatures; 800 | 801 | }; 802 | 803 | containerDimensions, 804 | The standard dimensions and coordinates of the container. 805 | inline, 806 | True if the container is anchored within the content the platform is presenting. False if the container is placed over the content. 807 | standardSize, 808 | Indicates whether the current dimensions are one of a standard size: default, max, min. 809 | default: the initial size of the container 810 | max: the standard maximum size the container allows. Maximum size may or may not be the full view available to the container but is the max size allowed. 811 | min: the minimum standard size the container offers. 812 | 813 | 814 | ``` 815 | 816 | 817 | 818 | ``` 819 | dictionary Dimensions { 820 | required long x; 821 | required long y; 822 | required long width; 823 | required long height; 824 | enum anchor; 825 | }; 826 | 827 | x, 828 | The x coordinate of the container anchor point. 829 | y, 830 | The x coordinate of the container anchor point. 831 | width, 832 | The width of the container in density-independent pixels. 833 | height, 834 | The height of the container in density-independent pixels. 835 | anchor, 836 | The anchor corner of the container: top-left, top-right, bottom-left, bottom-right. Default is top-left. 837 | ``` 838 | 839 | 840 | See [SHARC:Creative:requestPlacementChange](#sharc-creative-requestplacementchange) 841 | 842 |

SHARC:Container:log

843 | 844 | 845 | The purpose of the Container:log message is to convey optional, primarily debugging, information to the creative. 846 | 847 | 848 | ``` 849 | Note: In SHARC prefixing log messages with "WARNING:" has a specific meaning. The container is communicating performance inefficiencies or specification deviations aimed at creative developers. For example, if the creative sends the requestPlacementChange message but does not use the correct parameters (dimensions and coordinates), a "WARNING:" message is appropriate. 850 | ``` 851 | 852 | 853 | 854 | ``` 855 | dictionary MessageArgs{ 856 | required DOMString message; 857 | }; 858 | 859 | message, 860 | Logging information. 861 | ``` 862 | 863 | 864 |

SHARC:Container:fatalError

865 | 866 | 867 | The container posts a `SHARC:Container:fatalError` message when it encounters exceptions that disable any further function. If feasible, the container waits for `resolve` response from creative before unloading. 868 | 869 | See Container errors out 870 | 871 | 872 | ``` 873 | dictionary MessageArgs{ 874 | required unsigned short errorCode; 875 | DOMString errorMessage; 876 | }; 877 | 878 | errorCode, 879 | See Error Codes 880 | errorMessage, 881 | Additional information 882 | ``` 883 | 884 | 885 |
_resolve_
886 | 887 | 888 | The creative must respond to `Container:fatalError` with `resolve`. After `resolve` arrives, the container unloads. 889 | 890 | See Creative Errors Out 891 | 892 |

SHARC:Container:close

893 | 894 | 895 | The container provides a close control and handles the` Container:close` and subsequent` Container:unload` events. If supported, the container may allow the creative to run a close sequence that is no more than 2 seconds long. 896 | 897 | The container issues Container:close when: 898 | 899 | 900 | 901 | * The user activates the close control 902 | * The creative requests close with Creative:requestClose 903 | * Something in the content platform requires the container to close 904 |
905 | resolve
906 | 907 | 908 | 909 | The creative responds with resolve to acknowledge that the container is going to close. The container may proceed to unload with or without creative response. If supported, the container may wait for up to 2 seconds to allow the creative to run a close sequence. 910 | 911 |

Messages from the Creative to the Container

912 | 913 | 914 | The creative posts messages to the container to request container state changes, obtain data, and to send notifications. The creative prefixes its messages with the namespace `SHARC:Creative`. 915 | 916 | `SHARC:Creative` messages may require the container to accept and process arguments. With some messages, the creative expects the container to respond with resolutions. 917 | 918 |

SHARC:Creative:createSession

919 | 920 | 921 | The creative posts `SHARC:Creative:createSession` when the creative is ready to send and receive SHARC API messages. 922 | 923 |

SHARC:Creative:fatalError

924 | 925 | 926 | The creative posts `SHARC:Creative:fatalError` in cases when its internal exceptions prevent the interactive component from further execution. In response to the `Creative:fatalError` message, the container unloads the SHARC iframe and reports the `errorCode` specified by the creative. 927 | 928 | 929 | ``` 930 | dictionary MessageArgs{ 931 | required unsigned short errorCode; 932 | DOMString errorMessage; 933 | }; 934 | 935 | errorCode, 936 | See Error Codes. 937 | errorMessage, 938 | Additional information. 939 | ``` 940 | 941 | 942 |

SHARC:Creative:getContainerState

943 | 944 | 945 | The creative posts a `SHARC:Creative:getContainerState` message to request the current container state. 946 | 947 |
948 | _resolve_
949 | 950 | 951 | The container should always respond with `resolve`. 952 | 953 | 954 | ``` 955 | dictionary MessageArgs{ 956 | enum currentState; 957 | }; 958 | 959 | currentState, 960 | The current container state, which is one of: ready, active, inactivepassive, hidden, frozen, closing, destroyedunloaded. See Table of Possible Container States for definitions of states. 961 | ``` 962 | 963 | 964 |

SHARC:Creative:getPlacementOptions

965 | 966 | 967 | The creative posts a `SHARC:Creative:getPlacementOptions` message to request information about placement options. 968 | 969 |
970 | _resolve_
971 | 972 | 973 | The container should always respond with `resolve`, including in situations when the container is unable to provide all expected values. 974 | 975 | 976 | ``` 977 | dictionary MessageArgs{ 978 | required Placement currentPlacementOptions; 979 | }; 980 | 981 | currentPlacementOptions, 982 | Information about current container properties, such as dimensions and location. 983 | 984 | dictionary Placement { 985 | Dimensions containerDimensions; 986 | boolean inline; 987 | }; 988 | 989 | containerDimensions, 990 | The standard dimensions and coordinates of the container. 991 | inline, 992 | True if the container is anchored within the content of the platform. False if the container is placed over the content. 993 | 994 | ``` 995 | 996 | 997 |

SHARC:Creative:log

998 | 999 | 1000 | The message `SHARC:Creative:log` enables the creative to communicate arbitrary information to the player. 1001 | 1002 | 1003 | ``` 1004 | Note: If the log message purpose is to notify the container about the container's non-standard behavior, the creative prepends Message.args.message with "WARNING:" in the string. Warning messages are used to inform container developers about occurrences of non-fatal issues. 1005 | ``` 1006 | 1007 | 1008 | 1009 | ``` 1010 | dictionary MessageArgs{ 1011 | required DOMString message; 1012 | }; 1013 | 1014 | message, 1015 | Logging information. 1016 | ``` 1017 | 1018 | 1019 |

SHARC:Creative:reportInteraction

1020 | 1021 | 1022 | The `SHARC:Creative:reportInteraction` message enables a creative to delegate arbitrary non-navigation interaction metrics to the container. Standard interactions and macros are maintained separately from SHARC, so that an update to interaction metrics or macros doesn’t require a new version of SHARC. 1023 | 1024 | These interaction metrics are URIs into which the creative may inject macros. 1025 | 1026 | In response to the `reportInteraction` message, the container must: 1027 | 1028 | 1029 | 1030 | * Send the trackers specified by the message as soon as possible. 1031 | * Replace any macros in the dataspec with the corresponding values. 1032 | * Accept and send the trackers with custom macros – leave non-standard macros intact unless the publisher-ad integration involves custom macros processing. 1033 | 1034 | ``` 1035 | dictionary MessageArgs{ 1036 | required Array trackingUris; 1037 | }; 1038 | 1039 | trackingUris, 1040 | Array of URIs. 1041 | ``` 1042 | 1043 | 1044 | 1045 |
resolve
1046 | 1047 | 1048 | The player posts a `resolve` after it sends the trackers. 1049 | 1050 |

SHARC:Creative:requestNavigation

1051 | 1052 | 1053 | 1054 | The creative posts the` SHARC:Creative:requestNavigation` message when an interaction or some other event has triggered navigating to the creative’s clickthrough URI. 1055 | 1056 | 1057 | The container handles all navigation in situations where the function is available to the container. In some situations, such as in web, navigation is handled by the browser. However, even when the container cannot handle navigation to the creative’s link, _the creative must always request navigation_ so that the container is aware. 1058 | 1059 | 1060 | Navigation capabilities are provided upon initiation. See SHARC:Container:init.supports.navigation for details. 1061 | 1062 |

SHARC:Creative:requestPlacementChange

1063 | 1064 | 1065 | The creative posts the SHARC:Creative:requestPlacementChange message when the creative would like the container to modify its properties, such as size. 1066 | 1067 | 1068 | ``` 1069 | dictionary MessageArgs{ 1070 | required Placement changePlacement; 1071 | }; 1072 | 1073 | changePlacement, 1074 | Information about what container properties the creative would like to change. 1075 | 1076 | dictionary Placement { 1077 | Dimensions containerDimensions; 1078 | boolean inline; 1079 | }; 1080 | 1081 | containerDimensions, 1082 | The standard dimensions and coordinates of the container. 1083 | inline, 1084 | True if the container is anchored within the content of the platform. False if the container is placed over the content. 1085 | 1086 | ``` 1087 | 1088 | 1089 |
resolve
1090 | 1091 | 1092 | The container should always respond with `resolve`, including in situations when the container is unable to provide all expected values. The container should also post the [SHARC:Container:placementChange ](#sharc-container-placementchange)message with updates to any changes in properties to the container. 1093 | 1094 |

SHARC:Creative:requestClose

1095 | 1096 | 1097 | The container ALWAYS handles closing the container, including providing the close function. However, if the creative has a reason to close the container before the container’s close control is activated, the creative can post the SHARC:Creative:requestClose message to ask the container to close. 1098 | 1099 |
resolve
1100 | 1101 | 1102 | 1103 | If the container can close, it responds with a `resolve`. 1104 | 1105 |
reject
1106 | 1107 | 1108 | 1109 | If the container cannot close, it responds with a `reject`. 1110 | 1111 | 1112 | With the requestClose rejection: 1113 | 1114 | 1115 | 1116 | * The container maintains its current state. 1117 | * The container continues posting messages as appropriate. 1118 | * The creative may unload and send a Creative:log message to report that it has unloaded. 1119 | 1120 |

SHARC:Creative:getFeatures

1121 | 1122 | 1123 | The creative uses getFeatures to return a list of supported features.. 1124 | 1125 |
resolve
1126 | 1127 | 1128 | 1129 | The container returns a list of supported features. 1130 | 1131 |

SHARC:Creative:request[FeatureName]

1132 | 1133 | 1134 | The creative uses request[FeatureName] to initiate a supported feature. The SHARC container must be aware of and have implemented the named feature to execute it. 1135 | 1136 |
resolve
1137 | 1138 | 1139 | 1140 | The container responds with resolve upon execution of the feature and provides any relevant details as defined by the feature. 1141 | 1142 |
reject
1143 | 1144 | 1145 | 1146 | If the container cannot execute the requested feature or is unaware of the feature, it responds with a `reject`. 1147 | 1148 | 1149 | With the requestFeature rejection: 1150 | 1151 | 1152 | 1153 | * The container maintains its current state. 1154 | * The container continues posting messages as appropriate. 1155 | 1156 |

Extensions (Supported Features)

1157 | 1158 | 1159 | SHARC cannot account for all possible use cases. In these circumstances, SHARC implementers may include one or more extensions. Any extensions can be provided in the Supports node in init or by querying the container for extensions. 1160 | 1161 | SHARC maintains two types of feature extensions: SHARC-supported features and third party supported features. SHARC-supported features use the namespace `com.iabtechlab.sharc.[featureName]`. The nomenclature for third-party supported features is similar: `com.3rdpartyurl.sharc.[featureName]`. 1162 | 1163 | As long as the feature extensions are known and the technical functionality to support the feature is built in, any functionality can be built into SHARC by extension. 1164 | 1165 |

Integration with IAB Tech Lab Open Measurement

1166 | 1167 | 1168 | SHARC is designed to support additional features and integrations using its supported features extensions. Working with Open Measurement in SHARC requires that the container implementation supplies the functionality to execute the supported feature and that the creative knows how to call the feature. 1169 | 1170 | The Safe Ad Container working group will work with the Open Measurement to develop guidance on the use of a supported Open Measurement feature. As more resources become available, they will be posted at [iabtechlab.com/sharc](iabtechlab.com/sharc). 1171 | 1172 |

Common Workflows

1173 | 1174 | 1175 | To help SHARC developers and implementers, we’ve outlined some common workflows to demonstrate the functionality of SHARC as intended. 1176 | 1177 |

Loading (Ad Lifecycle)

1178 | 1179 | 1180 | (creating container, preparing to execute ad) 1181 | 1182 | Define the end-to-end lifecycle and break down by states 1183 | 1184 | 1185 | 1186 |

>>>>> gd2md-html alert: inline image link here (to images/image2.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

1187 | 1188 | 1189 | ![alt_text](images/image2.png "image_tooltip") 1190 | 1191 | 1192 |

Typical Initialization Workflow

1193 | 1194 | 1195 | 1196 | 1197 | 1. SHARC container is created and waits for a creative. 1198 | 2. Creative gets added to the SHARC enabled container 1199 | 3. Create Session happens 1200 | * Creative asks for session 1201 | * Resolve: Container creates session and sends info about what’s next (container set up) 1202 | * Reject: If session not created, reject includes details about why 1203 | 4. Container set up 1204 | * Container sets up container 1205 | * Sends details about environment, settings, etc. to creative 1206 | * Use case: mute button settings defined, creative sets creative with defined settings, tells container that it’s ready 1207 | * Creative must respond with resolve and reply with ready details. In the case of critical error, creative responds with reject and reports the error. 1208 | * Resolve: includes setting details 1209 | * Reject: critical error prevents creative from achieving ready state. The container is free to close and load something else. 1210 | 5. Start Creative (time to play the ad) 1211 | * Getting to this point means that both container/creative have said they’re ready to go and everything is in place. 1212 | 1213 |

Non-SHARC Creatives

1214 | 1215 | 1216 | SHARC as a container standard expects SHARC enabled creatives. However, as part of this standard, a SHARC enabled container must be able to render a standard HTML type of creative within its secure container, if possible, based on the container runtime environment. While the ad experience will not be as robust as a SHARC enabled experience, the publisher content will be protected by wrapping the creative in a secure container. 1217 | 1218 | However, SHARC dictates an initialization and start workflow for creatives. In cases where the creative won’t respond to the container, the container may assume that the creative is malfunctioning unless the creative gives a hint to the container that it isn’t SHARC enabled. As more detailed guidance becomes available, it will be posted to [iabtechlab.com/sharc](iabtechlab.com/sharc). 1219 | 1220 |

How to Handle Close Sequence

1221 | 1222 | 1223 | The container always handles close, but may allow for the creative to run a brief close (max 2 seconds) sequence upon initiating close to report and need tracking. Upon close, the container unloads the creative and the container. 1224 | 1225 | 1226 | 1227 | * User initiates close using container-provided close feature. 1228 | * Container reports that close has been initiated. 1229 | * If the container allows close sequence, it allows 2 seconds for the creative to run a close sequence, but the container may also close instantly. 1230 | * Container executes close. 1231 | 1232 | Note: Each SHARC instance only ever contains one ad. If a container wants to replace a closed ad with a new ad, it must unload an existing instance. The container then initiates a new instance for a new ad. If a container is reloading the same ad after a close, it must still be done within a new instance of the container. 1233 | 1234 |

How Container provides close control

1235 | 1236 | 1237 | SHARC mandates that the container provide the needed functionality for a user to close the ad experience. While the creative can opt to provide its own control, the container must present a control in a style that is consistent with the workflow governed by the container implementation. In general, it is assumed that the majority of close controls will be a button in the top right at a size of 50x50 DIPs. This is the most common type of close control and is recommended in most cases. 1238 | 1239 | However, this top right button can be replaced with a different type of close control as long as it is obvious to a user. For instance, if an application is a gallery of pictures that users swipe to go back and forth, the close control for an interstitial ad can be a swipe gesture since it is obvious to the user based on the preceding navigation. 1240 | 1241 | The container must always provide a close control that is obvious to a user to close the ad experience. 1242 | 1243 |

Creative Delays Resolving Init

1244 | 1245 | 1246 | The creative response to SHARC:Container:Init should be instant. If the creative does not respond to init within 2 seconds, the container may assume that creative cannot load and is free to unload the current instance and start a new one with a new ad. This delay in response can be handled the same way as if the creative sent a reject response (see Creative Rejects Init) 1247 | 1248 |

Creative Rejects Init

1249 | 1250 | 1251 | In the event that the creative rejects the container init message, the container assumes that there is a payload that is not functioning. In effect, this means that the container can be ready for another creative by disregarding the current payload. In this case, the container can do a few options, depending on the implementation desired. The listed options are not exhaustive. It is the container that will determine the best user experience and as such should maintain proper user workflow given the needs of the implementation. 1252 | 1253 | 1254 | 1255 | 1. Hide the SHARC container view. 1256 | 2. Request a new ad. 1257 | 1258 |

Error Handling and Timeouts

1259 | 1260 | 1261 | If the creative cannot be executed the container should terminate the ad and fire an error. 1262 | 1263 | If either the creative or container wants to terminate with an error the player should fire a 902 error. The creative or container should pass a specific error code to indicate why it errored out. The creative can also hand back a string with extra details about the error. 1264 | 1265 |

Error Codes

1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1273 | 1275 | 1277 | 1278 | 1279 | 1281 | 1283 | 1285 | 1286 | 1287 | 1289 | 1291 | 1293 | 1294 | 1295 | 1297 | 1299 | 1301 | 1302 | 1303 | 1305 | 1307 | 1309 | 1310 | 1311 | 1313 | 1315 | 1317 | 1318 | 1319 | 1321 | 1323 | 1325 | 1326 | 1327 | 1329 | 1331 | 1333 | 1334 | 1335 | 1337 | 1339 | 1341 | 1342 | 1343 | 1345 | 1347 | 1349 | 1350 | 1351 | 1353 | 1355 | 1357 | 1358 | 1359 | 1361 | 1363 | 1365 | 1366 | 1367 | 1369 | 1371 | 1373 | 1374 | 1375 | 1377 | 1379 | 1381 | 1382 | 1383 | 1385 | 1387 | 1389 | 1390 | 1391 | 1393 | 1395 | 1397 | 1398 | 1399 | 1401 | 1403 | 1405 | 1406 | 1407 | 1409 | 1411 | 1413 | 1414 | 1415 | 1417 | 1419 | 1421 | 1422 | 1423 | 1425 | 1427 | 1429 | 1430 | 1431 | 1433 | 1435 | 1437 | 1438 | 1439 | 1441 | 1443 | 1445 | 1446 |
Code 1272 | Error 1274 | Description 1276 |
2100 1280 | Unspecified creative error 1282 | Catchall error when no existing code matches the error. Creative errors should be as specific as possible. 1284 |
2101 1288 | Resources could not be loaded 1290 | The SHARC creative tried to load resources but failed. 1292 |
2102 1296 | Container dimensions not suited to creative 1298 | The container dimensions provided were unmatched to the dimensions the creative specified. 1300 |
2103 1304 | Wrong SHARC version 1306 | The creative could not support the container’s version of SHARC. 1308 |
2104 1312 | Creative could not be executed 1314 | For an unspecified technical reason, the creative could not be executed. 1316 |
2105 1320 | Resize request not honored 1322 | The container rejected the creative’s resize request. 1324 |
2108 1328 | Ad internal error 1330 | The creative had an error not related to any external dependencies. 1332 |
2109 1336 | Device not supported 1338 | The creative could not render or execute on the device. 1340 |
2110 1344 | Container not sending messages as specified 1346 | The container is sending messages but not according to spec. Messages are confusing, labeled incorrectly, or not listed. 1348 |
2111 1352 | Container not responding adequately to messages 1354 | Container is responding to messages but is delayed or without expected information. 1356 |
2200 1360 | Unspecified container error 1362 | Catchall error when no existing code matches the error. Container errors should be as specific as possible. 1364 |
2201 1368 | Wrong SHARC version 1370 | The container could not support the creative’s version of SHARC. 1372 |
2203 1376 | SHARC creative requesting more functionality than container willing to support 1378 | The creative may be requesting features that are unknown to the container or that the container doesn’t support. 1380 |
2204 1384 | SHARC creative executing actions not supported 1386 | While creative execution should be isolated from publisher content in a SHARC container, the creative may be attempting to execute unsupported features. 1388 |
2205 1392 | SHARC creative is overloading the postmessage channel 1394 | The creative is sending too many messages. 1396 |
2208 1400 | SHARC creative taking too long to resolve or reject message(s) 1402 | 1404 |
2209 1408 | SHARC creative provided is not supported on this device 1410 | 1412 |
2210 1416 | creative is not following the spec when initializing 1418 | 1420 |
2211 1424 | creative is not following the spec in the way it sends messages 1426 | 1428 |
2212 1432 | creative did not reply to the initialization message 1434 | 1436 |
2213 1440 | creative did not reply to the start message 1442 | 1444 |
1447 | 1448 | 1449 |

Messaging Protocol

1450 | 1451 | 1452 | 1453 | In SHARC, the media container and the creative overlay communicate by exchanging asynchronous signals that maintain a custom messaging protocol. 1454 | 1455 | 1456 | This protocol governs: 1457 | 1458 | 1459 | 1460 | * [Data Layer](#data-layer) 1461 | * [Transport Layer](#transport-layer) 1462 | * [Session Layer](#session-layer) 1463 |

1464 | Data Layer

1465 | 1466 | 1467 | 1468 | SHARC messages transport data. In HTML environments, the data is the `message` argument of the `Window.postMessage()` function. 1469 | 1470 |

1471 | Data Structure

1472 | 1473 | 1474 | The `message` data implements the following data structure for an HTML environment: 1475 | 1476 | 1477 | ``` 1478 | dictionary Message{ 1479 | required DOMString sessionId; 1480 | required unsigned long messageId; 1481 | required unsigned long timestamp; 1482 | required DOMString type; 1483 | any args; 1484 | }; 1485 | ``` 1486 | 1487 | 1488 | 1489 | **sessionId, 1490 | 1491 | 1492 | A string that uniquely identifies the session to which Message belongs. See [Session Layer.](#session-layer) 1493 | 1494 | 1495 | **messageId, 1496 | 1497 | 1498 | A message sequence number in the sender’s system. Each participant establishes its own independent sequence counter for the session. The first message `messageId` value is `0`. The sender increments each subsequent messageId value by `1`. In practice, this means that the creative and the container `messageId` values will be different based on the number of sent messages. 1499 | 1500 | 1501 | **timestamp, 1502 | 1503 | 1504 | A number of milliseconds since January 1, 1970, 00:00:00 UTC (Epoch time). The message sender must set the `timestamp` value as close as possible to the moment the underlying process occurs. However, the receiver should not assume that the `timestamp` value reflects the exact instant the message-triggering event occurred, not necessarily the time of the event. 1505 | 1506 | 1507 | **type, 1508 | 1509 | 1510 | A string that describes the message-underlying event and informs the receiver how to interpret the `args` parameter. 1511 | 1512 | 1513 | **args, 1514 | 1515 | 1516 | Additional information associated with the message `type`. 1517 | 1518 | 1519 | **Example of message data:** 1520 | 1521 | 1522 | ``` 1523 | { 1524 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 1525 | messageId: 10, 1526 | timestamp: 1564501643047, 1527 | type: "SHARC:Container:adClosed", 1528 | args: { 1529 | code: 0 1530 | } 1531 | } 1532 | ``` 1533 | 1534 | 1535 |

1536 | Messages Categories

1537 | 1538 | 1539 | The protocol defines two message classes: 1540 | 1541 | 1542 | 1543 | * **_Primary_** messages - the signals triggered by the sender’s internal logic. 1544 | * **_Response_** messages - the signals the receiver transmits as acknowledgments of the primary message receipt and processing. There are two response Message types: resolve Messages and reject Messages. 1545 | 1546 | Both primary and response messages implement the same data structure (see [Data Structure](#data-structure)). 1547 | 1548 |
1549 | `resolve` Messages
1550 | 1551 | 1552 | 1553 | The receiver confirms successful message processing by replying with a resolution message. 1554 | 1555 | `Message.type` must be `resolve`. 1556 | 1557 | `Message.args` must be a `ResolveMessageArgs` object: 1558 | 1559 | 1560 | ``` 1561 | dictionary ResolveMessageArgs{ 1562 | required unsigned long messageId; 1563 | any value; 1564 | }; 1565 | ``` 1566 | 1567 | 1568 | 1569 | **messageId, 1570 | 1571 | 1572 | The value of the messageId attribute of the message to which the receiver responds. 1573 | 1574 | 1575 | **value, 1576 | 1577 | Additional data associated with this `resolve` message. 1578 | 1579 | 1580 | **Example of resolve message: 1581 | 1582 | 1583 | ``` 1584 | { 1585 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 1586 | messageId: 10, 1587 | timestamp: 1564501643047, 1588 | type: "resolve", 1589 | args: { 1590 | messageId: 5, 1591 | value: { 1592 | id: 45 1593 | } 1594 | } 1595 | } 1596 | ``` 1597 | 1598 | 1599 |

1600 | **reject Messages

1601 | 1602 | 1603 | When the receiver is unable to process the message (or refuses it), it responds with rejection. 1604 | 1605 | `Message.type` must be `reject`. 1606 | 1607 | `Message.args.value` must be a `RejectMessageArgsValue` object: 1608 | 1609 | 1610 | ``` 1611 | dictionary RejectMessageArgsValue{ 1612 | required unsigned long errorCode; 1613 | DOMString message; 1614 | }; 1615 | ``` 1616 | 1617 | 1618 | 1619 | **errorCode, 1620 | 1621 | 1622 | The error code associated with the reason the receiver `rejects` the message. 1623 | 1624 | 1625 | **message, 1626 | 1627 | Additional information. 1628 | 1629 | 1630 | **Example of reject message: 1631 | 1632 | 1633 | ``` 1634 | { 1635 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 1636 | messageId: 10, 1637 | timestamp: 1564501643047, 1638 | type: "reject", 1639 | args: { 1640 | messageId: 5, 1641 | value: { 1642 | errorCode: 902, 1643 | message: "The feature is not available." 1644 | } 1645 | } 1646 | } 1647 | ``` 1648 | 1649 | 1650 |

1651 | Transport Layer

1652 | 1653 | 1654 | Transport is a communication mechanism that can send serialized messages between two parties. 1655 | 1656 |

1657 | **postMessage Transport

1658 | 1659 | 1660 | In HTML environments, where the container loads creative overlay in a cross-origin iframe, the parties utilize the standard `Window.postMessage()` API as the message transport mechanism. 1661 | 1662 |

1663 | **Message Serialization**

1664 | 1665 | 1666 | The message sender serializes data into a `JSON` string. The deserialized `JSON` must result in a clone of the original Message data object. 1667 | 1668 | In JavaScript, `JSON.stringify()` performs serialization; `JSON.parse()` - deserialization. 1669 | 1670 |

1671 | Session Layer

1672 | 1673 | 1674 | The media container may manage several ads that are in different phases of their lifespans; multiple concurrent sessions may be active. For example, while the container is rendering ad-A, it preloads and engages ad-B. Simultaneous two-way communication between the container and both ads persists. 1675 | 1676 | Each session has a unique identifier. All messages that belong to a specific session must reference the same session id. 1677 | 1678 |

1679 | Establishing a New Session

1680 | 1681 | 1682 | 1683 | The `createSession` message is the signal from the creative to the SHARC container that the underlying rich media is ready to proceed in the ad lifecycle and ready to send and receive further messages. 1684 | 1685 | SHARC delegates the session initialization to the creative overlay. The creative generates a unique session id and posts the first session message with the `Message.type createSession`. By posting the `createSession `message, the creative acknowledges its readiness to receive messages from the container. 1686 | 1687 | 1688 | Note: There is no expectation for the interactive component to be entirely able to participate in ad rendering at the time the creative signals `createSession` message. Full creative initialization may occur at later stages when the container provides complete data - see [§ 4.3.7 SHARC:container:init](https://interactiveadvertisingbureau.github.io/SIMID/#simid-player-init). 1689 | 1690 | 1691 | **Example of createSession Message data: 1692 | 1693 | 1694 | ``` 1695 | { 1696 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 1697 | messageId: 0, 1698 | timestamp: 1564501643047, 1699 | type: "createSession", 1700 | args: { } 1701 | } 1702 | ``` 1703 | 1704 | 1705 | Creative should initialize the session as soon as possible. The container should establish a reasonable timeout for the session initialization message receipt. 1706 | 1707 | The container responds to `createSession` with a `resolve` message. 1708 | 1709 | _Typical Session Initialization Sequence_ 1710 | 1711 | 1712 | 1713 |

>>>>> gd2md-html alert: inline image link here (to images/image3.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

1714 | 1715 | 1716 | ![alt_text](images/image3.png "image_tooltip") 1717 | 1718 | 1719 | 1720 | 1721 | 1. The container starts a `createSession` message timeout. 1722 | 2. The container loads creative. 1723 | 3. Creative posts `createSession` message. 1724 | 4. The container cancels the timeout. 1725 | 5. The container responds with a `resolve` message. 1726 | 6. The container initializes creative. See [SHARC:container:init](#sharc-container-init). 1727 |

1728 | Session Establishing Delays and Failures

1729 | 1730 | 1731 | 1732 | Typically, the container should wait for the creative to post a `createSession` message before proceeding to the simultaneous rendering of both ad media and the interactive component. However, SHARC recognizes scenarios when: 1733 | 1734 | 1735 | 1736 | * The creative fails to establish a session within the allotted time. 1737 | * The container’s environment restricts timeout usage (effectively, the timeout is zero). Specifically, SSAI and live broadcasts force zero-timeout use cases. 1738 | 1739 | The creative’s failure to establish a session does not prevent the container from rendering the ad media. If the creative does not post a `createSession` message on time, the container may proceed with the ad media rendering. However, the container allows the creative to recover in the middle of the ad media playback. The container: 1740 | 1741 | 1742 | 1743 | * Does not unload the creative. 1744 | * Does not post messages to the creative. 1745 | * Maintains the `creativeSession` message handler. 1746 | 1747 | If the creative has not established a session before the media playback is complete, the container will report a VAST Error tracker with the proper error code. Examples of situations when this may occur are listed below. 1748 | 1749 | **Sequence for a failed session initialization** 1750 | 1751 | 1752 | 1753 | 1. The timeout expires. 1754 | 2. The `createSession` message does not arrive. 1755 | 3. The container starts ad media. 1756 | 4. The container reports the impression. 1757 | 5. The ad media playback completes. 1758 | 6. The container reports the VAST error tracker. 1759 | 7. The container unloads the creative iframe. 1760 | 1761 | **Creative posts a createSession message after the timeout occurs 1762 | 1763 | 1764 | 1765 | 1. The timeout expires. 1766 | 2. The container retains the interactive component. 1767 | 3. The container initiates ad media playback. 1768 | 4. The container reports the impression. 1769 | 5. The container does not post messages to the creative. 1770 | 6. The creative posts `createSession` message. 1771 | 7. The container proceeds with the creative initialization. 1772 | 1773 |

Compatibility Modes

1774 | 1775 | 1776 | SHARC does NOT support MRAID or SafeFrame, but for adoption SHARC is working on bridge layers to work with MRAID or SafeFrame. 1777 | 1778 |

Compatibility Mode with MRAID

1779 | 1780 | 1781 | The SHARC working group is working on a compatibility bridge to enable transitioning from MRAID to SHARC. 1782 | 1783 |

Compatibility Mode with SafeFrame

1784 | 1785 | 1786 | The SHARC working group is working on a compatibility bridge to enable transitioning from MRAID to SHARC. 1787 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | A **Contributor License Agreement (CLA)** defines the terms under which intellectual property has been contributed to a company/project. The purpose of a CLA is to ensure that IAB Tech Lab has the necessary grants of rights over all contributions to allow them to be distributed under the chosen license. 2 | 3 | Contributors to the projects will be made under one or more roles as defined below: 4 | 5 | - **Project Release Manager** is overall responsible for the development of the project and has write access to the repository 6 | - **Committer** is a developer with write access to the repository and responsible for making final changes. 7 | - **Developer** is a contributor to the project in form of code or documentation and may take on other responsibilities for managing the project 8 | 9 | All contributors who wish to or are required to have write access **(Committers)** need to be/do one of the following: 10 | 11 | - Be a member of a Tech Lab member company (no additional paperwork required) 12 | - OR execute the [Contributor License Agreement](https://iabtechlab.com/wp-content/uploads/2021/07/IAB-TL-Contributor-License-Agreement.pdf) 13 | 14 | To become a **Committer**, please email [support@iabtechlab.com](mailto:support@iabtechlab.com) with the link to the project repository to which you’d like to commit as well as the signed copy of the Contributor License Agreement if required. 15 | -------------------------------------------------------------------------------- /messaging_protocol.md: -------------------------------------------------------------------------------- 1 | # DRAFT INSPRIATION FROM SIMID 2 | 3 | # API Reference 4 | 5 | ## SHARC:Container:init 6 | The purpose of the SHARC:Container:init message is to transport data to assist with the creative initialization process. See § 6.2 Typical Initialization WorkFlow and § 6.4 Uninterrupted Initialization WorkFlow. (TODO: determine where to put on doc) 7 | 8 | The creative must respond to the SHARC:Container:init message with either § 4.3.7.1 resolve or § 4.3.7.2 reject. (TODO) 9 | ``` 10 | dictionary MessageArgs 11 | { 12 | required EnvironmentData environmentData; 13 | required MetaData metaData; 14 | optional IdentifyData identityData; 15 | }; 16 | 17 | environmentData, 18 | Information about container's environment and capacities. 19 | metaData, 20 | Information about how to handle certain types of clickthroughs and other specific user workflow items //TODO: Revisit use cases 21 | identityData 22 | Information about the specific user or device. 23 | ``` 24 | 25 | ``` 26 | dictionary environmentData { 27 | required Dimensions containerDimensions; 28 | required boolean fullscreen; 29 | required boolean fullscreenAllowed; // TODO: Follow up on this 30 | required DOMString version; 31 | DOMString siteUrl; 32 | DOMString appId; 33 | DOMString deviceId; 34 | boolean muted; 35 | float volume; 36 | DOMString sdk; // the company and product or service making the request 37 | DOMString sdkVersion; 38 | dictionary identityData; // any data for identifying things like GDPR string, etc. TODO: more to flesh out? document list of possibilities. (MRAID had "limit tracking" for example) 39 | NavigationSupport navigationSupport; // Do we include this and how do we define it? This is about the click and who handles it: container or creative. Note: consider a compatibility mode that allows non-SHARC creative to execute in SHARC container. 40 | CloseInteractionSupport closeInteractionSupport; // container ALWAYS handles this and not allow creative to operate. But container could offer options such: white for black bkgd, or black for white background, or left/right, etc. Might not be a button; might be a swipe or other gesture. This data point not needed because it will be understood that container always provides close, but other creative doc needed on things like how to provide the close button/option, creative, communication, tech operation. 41 | }; 42 | 43 | dictionary Dimensions { 44 | required long x; 45 | required long y; 46 | required long width; 47 | required long height; 48 | }; // density-independent pixels 49 | 50 | 51 | 52 | enum NavigationSupport {"containerHandles", "notSupported"}; // TODO: determine how clicks handled and what options offered 53 | enum CloseInteractionSupport {}; // TODO: update to possibly provide close options 54 | 55 | containerDimensions, 56 | Communicates container coordinates and size when the container is present in the view hiearchy. -1 indicates an unknown value. 57 | fullscreen, 58 | The value true indicates that the container is currently in fullscreen mode. 59 | fullscreenAllowed, 60 | Communicates the container's capacity to toggle screen modes. 61 | 62 | The value true indicates that creative may request screen mode change. 63 | The value false denotes that the container will reject calls to change screen mode.* 64 | version, 65 | The SHARC version the container implements. 66 | muted, 67 | true if the environment § is muted.◊ 68 | volume, 69 | environment's § volume – expressed as a number between 0 and 1.0. 70 | sdk, 71 | Used for debugging purposes. The SDK provider. (IE: If a network provides the SDK to a publisher, put the name of the network or the specific product name) 72 | sdkVersion, 73 | Used for debugging purposes. The SDK version that the container uses. 74 | siteUrl, 75 | The URI of the publisher’s site. May be full or partial URL. 76 | appId, 77 | The ID of the mobile app, if applicable. 78 | navigationSupport, 79 | Indicates how clickthroughs should be handled. //TODO: Update description when use cases are discovered. 80 | 81 | closeInteractionSupport, 82 | //TODO: Update description when use cases are discovered. 83 | ``` 84 | 85 | ``` 86 | dictionary MetaData { 87 | 88 | }; // TODO: determine use cases for this. Data that is not about the environment but additional data that might be needed (enriched data). Determine list of metadata to use. 89 | 90 | ``` 91 | 92 | ``` 93 | dictionary IdentityData { 94 | DOMString ifa; 95 | DOMString useragent; 96 | DOMString cookieid; 97 | DOMString consentString; 98 | 99 | }; // TODO: What optional information can we pass here. Note, this doesn't mean they will be, just what CAN be passed. 100 | 101 | ``` 102 | 103 | SHARC does not expect device audio state information to be available at all times. 104 | Values of muted and volume are independent. While the player is muted, volume can be greater than zero; the volume zero does not mean the environment is muted. 105 | 106 | ### resolve 107 | 108 | The creative acknowledges the initialization parameters. 109 | 110 | If the creative delays calling resolve, see § 6.5 Creative Delays Resolving Init. 111 | ### reject 112 | 113 | The creative may respond with a reject based on its internal logic. 114 | ``` 115 | dictionary MessageArgs 116 | { 117 | required unsigned short errorCode; 118 | DOMString reason; 119 | }; 120 | 121 | errorCode, 122 | See Error Codes. (TODO) 123 | reason, 124 | Optional information about rejection cause. 125 | ``` 126 | The player then will follow the rejection workflow. See Creative Rejects Init. (TODO) 127 | 128 | # Messaging Protocol 129 | In SHARC, the container and the creative communicate by exchanging asynchronous signals that maintain a custom messaging protocol. This protocol governs [8.1 Data Layer](#81-data-layer), [8.3 Transport Layer](#83-transport-layer), and [8.4 Session Layer](#84-session-layer). 130 | 131 | ## 8.1. Data Layer 132 | SHARC messages transport data. In HTML environments, the data is the `message` argument of the Window.postMessage() function. 133 | 134 | ### 8.1.1. Data Structure 135 | The `message` data implements the following data structure: 136 | ``` 137 | dictionary Message { 138 | required DOMString sessionId; 139 | required unsigned long messageId; 140 | required unsigned long timestamp; 141 | required DOMString type; 142 | any args; 143 | } 144 | ``` 145 | `sessionId` 146 | A string that uniquely identifies the session to which Message belongs. See [8.4 Session Layer](#84-session-layer). 147 | 148 | `messageId` 149 | A message sequence number in the sender’s system. Each participant establishes its own independent sequence counter for the session. The first message `messageId` value is `0`. The sender increments each subsequent messageId value by `1`. In practice, this means that the creative and the container `messageId` values will be different based on the number of sent messages. 150 | 151 | `timestamp` 152 | A number of milliseconds since January 1, 1970, 00:00:00 UTC (Epoch time). The message sender must set `timestamp` value as close as possible to the moment the underlying process occurs. However, the receiver should not assume that the `timestamp` value reflects the exact instant the message-triggering event occurred. 153 | 154 | `type` 155 | A string that describes the message-underlying event and informs the receiver how to interpret the `args` parameter. 156 | 157 | `args` 158 | Additional information associated with the message `type`. 159 | 160 | Example of message data: 161 | ``` 162 | { 163 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 164 | messageId: 10, 165 | timestamp: 1564501643047, 166 | type: "SHARC:Player:adStopped", 167 | args: { 168 | code: 0 169 | } 170 | } 171 | ``` 172 | 173 | ## 8.2. Messages Categories 174 | The protocol defines two message classes: 175 | 176 | - Primary messages - the signals triggered by the sender’s internal logic. 177 | - Response messages - the signals the receiver transmits as acknowledgments of the primary message receipt and processing. There are two response Message types: [8.2.1 resolve Messages](821-resolve-messages) and [8.2.2 reject Messages](#822-reject-messages). 178 | 179 | Both primary and response messages implement the same data structure (see [8.1.1 Data Structure](#811-data-structure)). 180 | 181 | ### 8.2.1. resolve Messages 182 | The receiver confirms successful message processing by replying with a resolution message. 183 | 184 | `Message.type` must be `resolve`. 185 | 186 | `Message.args` must be a `ResolveMessageArgs` object: 187 | ``` 188 | dictionary ResolveMessageArgs { 189 | required unsigned long messageId; 190 | any value; 191 | }; 192 | ``` 193 | 194 | `messageId` 195 | The value of the `messageId` attribute of the message to which the receiver responds. 196 | 197 | `value` 198 | Additional data associated with this `resolve` message. 199 | 200 | Example of `resolve` message: 201 | ``` 202 | { 203 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 204 | messageId: 10, 205 | timestamp: 1564501643047, 206 | type: "resolve", 207 | args: { 208 | messageId: 5, 209 | value: { 210 | id: 45 211 | } 212 | } 213 | } 214 | ``` 215 | 216 | ### 8.2.2. reject Messages 217 | When the receiver is unable to process the message, it responds with a rejection. 218 | 219 | `Message.type` must be `reject`. 220 | 221 | `Message.args.value` must be a `RejectMessageArgsValue` object: 222 | 223 | ``` 224 | dictionary RejectMessageArgsValue { 225 | unsigned long errorCode; 226 | DOMString message; 227 | }; 228 | ``` 229 | 230 | `errorCode` 231 | The error code associated with the reason the receiver rejects the message. 232 | 233 | `message` 234 | Additional information. 235 | 236 | Example of `reject` message: 237 | ``` 238 | { 239 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 240 | messageId: 10, 241 | timestamp: 1564501643047, 242 | type: "resolve", 243 | args: { 244 | messageId: 5, 245 | value: { 246 | errorCode: 902, 247 | message: "The feature is not available." 248 | } 249 | } 250 | } 251 | ``` 252 | ## 8.3. Transport Layer 253 | The transport layer is a communication mechanism that can send serialized messages between two parties. 254 | 255 | ### 8.3.1. `postMessage` Transport 256 | In HTML environments, where the container is a secure IFrame, the parties utilize the standard `Window.postMessage()` API as the message transport mechanism. 257 | 258 | ### 8.3.2. Message Serialization 259 | The message sender serializes data into a JSON string. The deserialized JSON must result in a clone of the original Message data object. 260 | 261 | In JavaScript, `JSON.stringify()` performs serialization; `JSON.parse()` - deserialization. 262 | 263 | ## 8.4. Session Layer 264 | The container may manage several ads that are in different phases of their lifecycle; multiple concurrent sessions may be active. For example, while the container is rendering ad-A, it preloads and engages ad-B. Simultaneous two-way communication between the player and both ads persists. 265 | 266 | Each session has a unique identifier. All messages that belong to a specific session must reference the same session id. 267 | 268 | ### 8.4.1 Establishing a New Session 269 | SHARC delegates the session initialization to the container. The creative generates a unique session id and posts the first session message with the Message.type `createSession`. By posting the `createSession` message, the creative acknowledges its readiness to receive messages from the container. 270 | 271 | #### Note: There is no expectation for the interactive creative component to be entirely able to participate in ad rendering at the time the creative signals `createSession` message. Full creative initialization may occur at later stages when the container provides complete data - see SHARC:Container:init. 272 | 273 | Example of `createSession` Message data: 274 | ``` 275 | { 276 | sessionId: "173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4", 277 | messageId: 0, 278 | timestamp: 1564501643047, 279 | type: "createSession", 280 | args: { } 281 | } 282 | ``` 283 | The creative must initialize the session as soon as possible. The container should establish a reasonable timeout for the session initialization message receipt. 284 | 285 | The container responds to `createSession` with a `resolve` message. 286 | 287 | 288 | 289 | ### 8.4.2. Session Establishing Delays and Failures 290 | 291 | Typically, the container must wait for the creative to post a `createSession` message. However, SHARC recognizes that a container may have a specific timeout to ensure that the ad experience for a consumer is maintained. In this scenario, the container can unload the existing creative and load a new one, or provide an alternative behavior to preserve a good consumer experience. The series of events are as follows: 292 | 293 | * The timeout expires. 294 | * The `createSession` message does not arrive. 295 | * The container unloads the creative. 296 | * The container elects to collapse its view. 297 | -------------------------------------------------------------------------------- /sharc/README.md: -------------------------------------------------------------------------------- 1 | # SHARC POC 2 | 3 | This is a proof of concept of SHARC (Secure HTML Ad Richmedia Container). A secure container API for managed 4 | communication between an app or webpage and a served ad creative. 5 | 6 | ## Lifecycle 7 | ![This is an image](sharc-lifecycle.png) 8 | 9 | ## Structure 10 | 11 | ``` 12 | ├── creatives 13 | │   ├── video-creative.html 14 | │   └── video-creative.js 15 | ├── sharc-protocol.js 16 | ├── template.html 17 | └── template.js 18 | ``` 19 | This poc follows the lifecycle provided above: 20 | - Open `template.html` in your browser and click on the `Init Ad` button 21 | - Then the template will be in charge of creating a secure iFrame and listen for the protocol message `CREATE_SESSION` 22 | - In the `video-creative.html` once the video is ready to play and buffering is complete the creative creates a new SHARC session 23 | - The `template` is now aware that a new session has been created, then it sends details about environment, settings, etc. to the `video creative` 24 | - Then the `video creative` receives container details, prepare the video options and responds with ready details 25 | - Once we reach this this point it means that both `template/video-creative` have said they’re ready to 26 | go and everything is in place. 27 | - Video starts 28 | -------------------------------------------------------------------------------- /sharc/SHARC.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/SHARC/617c5c9ce5d2b0bc328d5160c6aa808a8b6ae656/sharc/SHARC.zip -------------------------------------------------------------------------------- /sharc/creatives/video-creative.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 26 | 27 | 28 |
29 |
30 | 40 |
41 |
42 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sharc/creatives/video-creative.js: -------------------------------------------------------------------------------- 1 | const sharcProtocol = new SHARCProtocol(); 2 | 3 | function addListeners() { 4 | sharcProtocol.addListener(ContainerMessages.INIT, (args) => { 5 | sharcProtocol.resolve(args, {}); 6 | prepareCreative(args); 7 | }); 8 | 9 | sharcProtocol.addListener(ContainerMessages.START_CREATIVE, (args) => { 10 | sharcProtocol.resolve(args, {}); 11 | initCreative(args); 12 | }); 13 | 14 | sharcProtocol.addListener(ContainerMessages.CLOSE, (args) => { 15 | sharcProtocol.resolve(args, {}); 16 | }); 17 | } 18 | 19 | function prepareCreative(data) { 20 | const videoEl = document.getElementById('video_player'); 21 | const { muted } = data.args.environmentData; 22 | videoEl.muted = muted; 23 | } 24 | 25 | function initCreative(data) { 26 | const videoEl = document.getElementById('video_player'); 27 | videoEl.play(); 28 | } 29 | 30 | function init() { 31 | document.getElementById('video_player').addEventListener('canplaythrough', () => { 32 | sharcProtocol.createSession(); 33 | addListeners(); 34 | }); 35 | } -------------------------------------------------------------------------------- /sharc/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/SHARC/617c5c9ce5d2b0bc328d5160c6aa808a8b6ae656/sharc/favicon.ico -------------------------------------------------------------------------------- /sharc/sharc-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/SHARC/617c5c9ce5d2b0bc328d5160c6aa808a8b6ae656/sharc/sharc-lifecycle.png -------------------------------------------------------------------------------- /sharc/sharc-protocol.js: -------------------------------------------------------------------------------- 1 | class SHARCProtocol { 2 | constructor() { 3 | this.sessionId = ''; 4 | this.nextMessageId = 1; 5 | this.listeners = {}; 6 | this.messageTarget = window.parent; 7 | this.resolutionListeners = {}; 8 | window.addEventListener('message', this.receiveMessage.bind(this), false); 9 | } 10 | 11 | sendMessage(messageType, messageArgs) { 12 | const messageId = this.nextMessageId++; 13 | const getMessageType = messageType === ProtocolMessages.CREATE_SESSION ? messageType : `SHARC:${messageType}`; 14 | const message = { 15 | sessionId: this.sessionId, 16 | messageId: messageId, 17 | type: getMessageType, 18 | timestamp: Date.now(), 19 | args: messageArgs, 20 | }; 21 | 22 | console.log('MESSAGE: ', message); 23 | if (MessagesThatRequireResponse.includes(messageType)) { 24 | return new Promise((resolve, reject) => { 25 | this.addResolveAndRejectListeners( 26 | messageId, 27 | resolve, 28 | reject 29 | ); 30 | this.messageTarget.postMessage(JSON.stringify(message), '*'); 31 | }); 32 | } 33 | return new Promise((resolve, reject) => { 34 | this.messageTarget.postMessage(JSON.stringify(message), '*'); 35 | resolve(); 36 | }); 37 | } 38 | 39 | addListener(messageType, callback) { 40 | if (!this.listeners[messageType]) { 41 | this.listeners[messageType] = [callback]; 42 | } else { 43 | this.listeners[messageType].push(callback); 44 | } 45 | } 46 | 47 | callListenersByType(type, data) { 48 | const listeners = this.listeners[type]; 49 | 50 | if (listeners) { 51 | listeners.forEach((listener) => listener(data)); 52 | } 53 | } 54 | 55 | receiveMessage(event) { 56 | if (!event || !event.data) return; 57 | 58 | const data = JSON.parse(event.data); 59 | 60 | if (!data) return; 61 | 62 | const sessionId = data['sessionId']; 63 | const type = data['type']; 64 | const isSessionCreation = this.sessionId === '' && type === ProtocolMessages.CREATE_SESSION; 65 | const hasSessionMatch = this.sessionId === sessionId; 66 | const isValidSessionId = isSessionCreation || hasSessionMatch; 67 | 68 | if (!isValidSessionId || type === null) return; 69 | 70 | if (Object.values(ProtocolMessages).includes(type)) { 71 | this.handleProtocolMessages(data); 72 | } else if (type.startsWith('SHARC:')) { 73 | this.callListenersByType(type.substr(6), data); 74 | } 75 | } 76 | 77 | handleProtocolMessages(data) { 78 | const type = data['type']; 79 | 80 | switch (type) { 81 | case ProtocolMessages.CREATE_SESSION: 82 | this.sessionId = data['sessionId']; 83 | this.handleIncomingMessage(data, {}, ProtocolMessages.RESOLVE); 84 | this.callListenersByType(type, data); 85 | break; 86 | case ProtocolMessages.RESOLVE: 87 | // TDB 88 | case ProtocolMessages.REJECT: 89 | const args = data['args']; 90 | const argMessageId = args['messageId']; 91 | const resolutionListener = this.resolutionListeners[argMessageId]; 92 | if (resolutionListener) { 93 | resolutionListener(data); 94 | delete this.resolutionListeners[argMessageId]; 95 | } 96 | break 97 | } 98 | } 99 | 100 | resolve(incomingMessage, outgoingArgs) { 101 | const messageId = this.nextMessageId++; 102 | const resolveMessageArgs = { 103 | messageId: incomingMessage['messageId'], 104 | value: outgoingArgs, 105 | }; 106 | const message = { 107 | sessionId: this.sessionId, 108 | messageId: messageId, 109 | type: ProtocolMessages.RESOLVE, 110 | timestamp: Date.now(), 111 | args: resolveMessageArgs, 112 | }; 113 | 114 | this.messageTarget.postMessage(JSON.stringify(message), '*'); 115 | } 116 | 117 | createSession() { 118 | this._generateSessionId(); 119 | const createdSessionResolved = () => { console.log('Session created') }; 120 | const createdSessionRejected = () => { console.log('Session creation has failed ') }; 121 | 122 | this.sendMessage(ProtocolMessages.CREATE_SESSION).then( 123 | createdSessionResolved, 124 | createdSessionRejected, 125 | ); 126 | } 127 | 128 | addResolveAndRejectListeners(messageId, resolve, reject) { 129 | const listener = (data) => { 130 | const type = data['type']; 131 | const args = data['args']['value']; 132 | if (type === 'resolve') { 133 | resolve(args); 134 | } else if (type === 'reject') { 135 | reject(args); 136 | } 137 | }; 138 | 139 | this.resolutionListeners[messageId] = listener.bind(this); 140 | } 141 | 142 | handleIncomingMessage(incomingMessage, args, protocolMessage) { 143 | const messageId = this.nextMessageId++; 144 | const message = { 145 | sessionId: this.sessionId, 146 | messageId: messageId, 147 | type: protocolMessage, 148 | timestamp: Date.now(), 149 | args: { 150 | messageId: incomingMessage['messageId'], 151 | value: args, 152 | } 153 | }; 154 | 155 | this.messageTarget.postMessage(JSON.stringify(message), '*'); 156 | } 157 | 158 | reset() { 159 | this.listeners = {}; 160 | this.sessionId = ''; 161 | this.nextMessageId = 1; 162 | this.resolutionListeners = {}; 163 | } 164 | 165 | _generateSessionId() { 166 | const url = URL.createObjectURL(new Blob()); 167 | const [id] = url.toString().split('/').reverse(); 168 | URL.revokeObjectURL(url); 169 | this.sessionId = id; 170 | } 171 | 172 | setMessageTarget(target) { 173 | this.messageTarget = target; 174 | } 175 | } 176 | 177 | ProtocolMessages = { 178 | CREATE_SESSION: 'createSession', 179 | RESOLVE: 'resolve', 180 | REJECT: 'reject', 181 | }; 182 | 183 | ContainerMessages = { 184 | INIT: 'Container:init', 185 | START_CREATIVE: 'Container:startCreative', 186 | STATE_CHANGE: 'Container:stateChange', 187 | PLACEMENT_CHANGE: 'Container:placementChange', 188 | LOG: 'Container:log', 189 | FATAL_ERROR: 'Container:fatalError', 190 | CLOSE: 'Container:close', 191 | }; 192 | 193 | CreativeMessages = { 194 | FATAL_ERROR: 'Creative:fatalError', 195 | GET_CONTAINER_STATE: 'Creative:getContainerState', 196 | GET_PLACEMENT_OPTIONS: 'Creative:getPlacementOptions', 197 | LOG: 'Creative:log', 198 | REPORT_INTERACTION: 'Creative:reportInteraction', 199 | REQUEST_NAVIGATION: 'Creative:requestNavigation', 200 | REQUEST_PLACEMENT_CHANGE: 'Creative:requestPlacementChange', 201 | REQUEST_CLOSE: 'Creative:requestClose', 202 | }; 203 | 204 | MessagesThatRequireResponse = [ 205 | ContainerMessages.INIT, 206 | ContainerMessages.START_CREATIVE, 207 | ContainerMessages.FATAL_ERROR, 208 | ContainerMessages.CLOSE, 209 | CreativeMessages.GET_CONTAINER_STATE, 210 | CreativeMessages.GET_PLACEMENT_OPTIONS, 211 | CreativeMessages.REPORT_INTERACTION, 212 | CreativeMessages.REQUEST_PLACEMENT_CHANGE, 213 | CreativeMessages.REQUEST_CLOSE, 214 | ]; 215 | 216 | ContainerStates = { 217 | READY: 'ready', 218 | ACTIVE: 'active', 219 | PASSIVE: 'passive', 220 | HIDDEN: 'hidden', 221 | FROZEN: 'frozen', 222 | CLOSING: 'closing', 223 | UNLOADED: 'unloaded', 224 | }; 225 | 226 | CreativeErrorCodes = { 227 | UNSPECIFIED: 2100, 228 | CANNOT_LOAD_RESOURCES: 2101, 229 | NOT_SUITED_CREATIVE_DIMENSIONS: 2102, 230 | WRONG_SHARC_VERSION: 2103, 231 | CANNOT_EXECUTE_CREATIVE: 2104, 232 | RESIZE_REQUEST_NOT_HONORED: 2105, 233 | PAUSE: 2106, 234 | PLAYER_CONTROLS: 2107, 235 | AD_INTERNAL_ERROR: 2108, 236 | DEVICE_NOT_SUPPORTED: 2109, 237 | CONTAINER_NOT_SENDING: 2110, 238 | CONTAINER_NOT_RESPONDING: 2111, 239 | UNSPECIFIED_CONTAINER_ERROR: 2222, 240 | UNDEFINED: 2210, 241 | }; 242 | -------------------------------------------------------------------------------- /sharc/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #333; 3 | } 4 | 5 | .row { 6 | display: flex; 7 | flex-wrap: wrap; 8 | gap: 22px; 9 | } 10 | 11 | .column { 12 | min-width: 180px; 13 | } 14 | 15 | .event-box { 16 | min-height: 200px; 17 | margin: 20px 0; 18 | background: whitesmoke; 19 | font-size: 1em; 20 | font-family: monospace; 21 | white-space: normal; 22 | } 23 | 24 | .white-text { 25 | color: white; 26 | } 27 | /* The device with borders */ 28 | .smartphone { 29 | position: relative; 30 | width: 360px; 31 | height: 640px; 32 | margin: auto; 33 | border: 16px black solid; 34 | border-top-width: 60px; 35 | border-bottom-width: 60px; 36 | border-radius: 36px; 37 | } 38 | 39 | /* The horizontal line on the top of the device */ 40 | .smartphone:before { 41 | content: ''; 42 | display: block; 43 | width: 60px; 44 | height: 5px; 45 | position: absolute; 46 | top: -30px; 47 | left: 50%; 48 | transform: translate(-50%, -50%); 49 | background: #333; 50 | border-radius: 10px; 51 | } 52 | 53 | /* The circle on the bottom of the device */ 54 | .smartphone:after { 55 | content: ''; 56 | display: block; 57 | width: 35px; 58 | height: 35px; 59 | position: absolute; 60 | left: 50%; 61 | bottom: -65px; 62 | transform: translate(-50%, -50%); 63 | background: #333; 64 | border-radius: 50%; 65 | } 66 | 67 | /* The screen (or content) of the device */ 68 | .smartphone .content { 69 | width: 360px; 70 | height: 640px; 71 | background: white; 72 | } 73 | 74 | .close_button { 75 | position: absolute; 76 | right: 22px; 77 | top: 12px; 78 | width: 32px; 79 | height: 32px; 80 | opacity: 0.5; 81 | border-radius: 20px; 82 | background-color: #fff; 83 | padding: 2px; 84 | cursor: pointer; 85 | display: none; 86 | } 87 | .close_button:hover { 88 | opacity: 0.8; 89 | } 90 | .close_button:before, 91 | .close_button:after { 92 | position: absolute; 93 | top: 7px; 94 | left: 17px; 95 | content: ' '; 96 | height: 22px; 97 | width: 3px; 98 | background-color: #333; 99 | } 100 | .close_button:before { 101 | transform: rotate(45deg); 102 | } 103 | .close_button:after { 104 | transform: rotate(-45deg); 105 | } 106 | -------------------------------------------------------------------------------- /sharc/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SHARC - POC 9 | 10 | 11 | 12 | 13 |
14 |
15 |

Events:

16 |
17 |
18 |
19 |

Environment data:

20 | 23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /sharc/template.js: -------------------------------------------------------------------------------- 1 | const sharcProtocol = new SHARCProtocol(); 2 | 3 | function logEvent(eventName, eventArg) { 4 | const box = document.getElementById('events'); 5 | const paragraph = document.createElement('p'); 6 | let text = eventName + ' '; 7 | 8 | if (eventArg && eventArg instanceof Array) { 9 | for (var i = 0; i < eventArg.length; i++) { 10 | text = text + eventArg[i] + ' '; 11 | } 12 | } 13 | paragraph.innerText = text; 14 | box.appendChild(paragraph); 15 | } 16 | 17 | function disableEnableButton(id, status) { 18 | document.getElementById(id).disabled = status; 19 | } 20 | 21 | function createIframe() { 22 | const adIframe = document.createElement('iframe'); 23 | logEvent('iFrame has been created'); 24 | 25 | adIframe.style = 'width: 100%; border: none; height: 100%; display: none'; 26 | adIframe.src = 'creatives/video-creative.html'; 27 | adIframe.setAttribute('id', 'secure-iframe'); 28 | adIframe.setAttribute('allowFullScreen', ''); 29 | adIframe.setAttribute('allow', 'geolocation'); 30 | 31 | document.getElementById('smartphone-content').append(adIframe); 32 | logEvent('iFrame added to DOM'); 33 | sharcProtocol.setMessageTarget(adIframe.contentWindow); 34 | } 35 | 36 | function sendInitMessage() { 37 | let environmentData = { 38 | 'fullscreen': false, 39 | 'fullscreenAllowed': true, 40 | 'useragent': '', 41 | 'deviceId': '', 42 | 'muted': true, 43 | } 44 | 45 | const creativeData = { 46 | 'adId': '', 47 | 'creativeId': '', 48 | 'adServingId': '', 49 | } 50 | 51 | const envDataTextAreaValue = document.getElementById('env-data'); 52 | 53 | if (envDataTextAreaValue.value) { 54 | try { 55 | environmentData = JSON.parse(envDataTextAreaValue.value, null, 2); 56 | } catch (error) { 57 | console.error('Error: ', error); 58 | } 59 | } 60 | 61 | const initMessage = { 62 | 'environmentData': environmentData, 63 | 'creativeData': creativeData 64 | } 65 | 66 | logEvent('SHARC:Container:INIT called', sharcProtocol.sessionId); 67 | sharcProtocol.sendMessage(ContainerMessages.INIT, initMessage).then((args) => initialize(args)).catch((args) => console.error('args', args)); 68 | } 69 | 70 | function initialize(data) { 71 | document.getElementById('secure-iframe').style.display = 'block'; 72 | logEvent('Displaying the iFrame'); 73 | 74 | const closeButton = document.getElementById('close-button'); 75 | closeButton.style.display = 'block'; 76 | logEvent('Showing the close button'); 77 | 78 | closeButton.addEventListener('click', () => closeAd()); 79 | } 80 | 81 | function startCreative() { 82 | sharcProtocol.sendMessage(ContainerMessages.START_CREATIVE).then(() => logEvent('Creative has started')); 83 | disableEnableButton('btn-start-ad', true); 84 | } 85 | 86 | function closeAd() { 87 | sharcProtocol.sendMessage(ContainerMessages.CLOSE).then(() => { 88 | const adIframe = document.getElementById('secure-iframe').remove(); 89 | const closeButton = document.getElementById('close-button'); 90 | closeButton.removeEventListener('click', closeAd); 91 | closeButton.style.display = 'none'; 92 | disableEnableButton('btn-init-ad', false); 93 | disableEnableButton('btn-start-ad', false); 94 | document.getElementById('events').innerHTML = ''; 95 | sharcProtocol.reset(); 96 | }).catch((e) => console.error('Error closing the Ad', e)); 97 | } 98 | 99 | function addListeners() { 100 | sharcProtocol.addListener( 101 | ProtocolMessages.CREATE_SESSION, 102 | (args) => { 103 | logEvent('New SHARC session has been created with ID: ', [args.sessionId]); 104 | sendInitMessage(); 105 | }); 106 | } 107 | 108 | function initAd() { 109 | createIframe(); 110 | disableEnableButton('btn-init-ad', true); 111 | addListeners(); 112 | } 113 | --------------------------------------------------------------------------------