Skip to content

Release Notes

Highlights and behavior changes per release. The full changelog ships as CHANGELOG.md in the package.

Pin the SDK exactly and bump deliberately:

Terminal window
npm install @elo-ads/web-sdk@0.6.1 --save-exact
Latest View on npm
  • Change: the card is set like a feed ad, as on iOS and Android. <EloAd> draws a header row with a 36px image beside the title and the “Ad” disclosure on its own line under it, the description at full width on up to three lines, and the CTA button on a 44px row of its own at the trailing edge, or a chevron closing the header row. The card takes the height its copy needs. The strip is unchanged and still reads Ad • Headline. See Ad Formats and Rendering Ads.
  • Change: the card needs a 192px slot. The server’s threshold for the card moved from 80px to 192px, so a maxHeight from 72px to 191px gets the strip. A response that names no known format falls back the same way.
  • New Elo chooses what opens the ad when the creative has a CTA button. Elo sets per publisher and format whether the button is the ad’s only link or the whole ad is the link, with nothing to configure in code. The defaults keep 0.6.0’s behavior: the button alone on the strip, the whole ad on the card. EloDebugAdOperation reports the choice as tapSurface.
  • Fix A CTA button inside the ad’s own link is hidden from assistive technology. The link is named after the creative alone, on the card and the strip, as on iOS and Android.
Breaking changes View on npm
  • New Describe the slot, and the server chooses the format. Pass maxHeight (and optionally maxWidth), in CSS pixels, to sdk.fetchAds. The server returns the format that fits: the card needs 80px, the strip 72px, and a shorter slot gets no ad. <EloAd> renders whichever format the ad names, as ad.presentation.format. Leaving maxHeight unset keeps today’s card, so an integration that changes nothing sees nothing change. The strip is a single row for a slot beside the composer: a 40px mark, a one-line headline and description, and a trailing chevron or compact CTA button, 72px tall. When the creative carries a CTA, the button is the strip’s only link and the rest of the strip is inert, so a click near the composer that misses opens nothing. The container carries elo-ad-card or elo-ad-strip beside elo-ad. See Ad Formats and Rendering Ads.
  • New An id and time for each chat message. ChatMessage takes optional id and createdAt (a Date, or an ISO 8601 string with a time zone). Set them once, when the turn happens, and send the same values each time the turn is sent again. Elo then knows when each turn happened instead of only when the ad was requested, and the id matches Search API calls that send it as X-Elo-Message-Id. A summary message takes the id and time of the turn it summarizes. A value the SDK can’t use is left out with a console warning, and fetchAds now sends only role, content, id, and createdAt for each message, not other fields on your message objects.
  • New The publisher’s CTA settings apply on the web. The ad now carries presentation.cta_enabled and presentation.cta_variant, which Elo sets per publisher and format. cta_enabled: false hides the CTA button even when the creative sends cta_text. The icon variant adds an arrow after the label; icon_bounce and icon_shimmer add the arrow and, after the ad has been at least half visible for one second, a short pop or shimmer that repeats every few seconds while it stays in view. The motion is off when the reader prefers reduced motion. On the strip, presentation.tap_inset takes up to 14px off each edge of the link on creatives without a CTA; the strip draws the same.
  • Change: the card is 80px tall, and its copy is one line. The headline, description, and CTA label end in an ellipsis instead of wrapping, as on iOS and Android, so the card never grows past the height the server chose it for. The hairline border is drawn inside the card as an inset shadow and no longer adds 2px; a style or class that set border on .elo-ad should set box-shadow instead.
  • Change: ad requests no longer send display_position. They send dimensions instead, and the server records the position from the format it chose: card for a card and banner for a strip, the same values the mobile card and strip report. Web showings in the unbounded chat slot stay card.
  • Breaking sdk.getTrackingTotals() and the TrackingTotals type are removed; sdk.setDebugObserver(observer, { capturePayloads }) replaces them. The SDK now reports each event as it happens and keeps no counts of its own: initialized, ad_operation (the outcome of each fetchAds, with the slot sent and the format and settings received), and tracking_attempted / tracking_completed for render, impression, click, and tap. A page that wants totals counts the events. With capturePayloads, it also receives the ad request body with message content and context descriptions removed, the ad response, and the body each tap posts. It is the same debug observer as iOS and Android 0.6.0. TrackingEvent now includes click. See the API Reference.
  • Fix A tap that opened nothing sends no click notice. sdk.trackTap sent the demand source’s click notices for every tap. It now sends them only for a tap with opened: true.
  • Demand-source notices are sent from the reader’s browser. Some demand sources ask for the notice that an ad was displayed or clicked to come from the reader rather than from Elo’s servers, so their systems see the request as the reader’s. An ad can now carry a trackers list, and <EloAd> sends each entry at the moment it names: display, viewable impression, or click, for pointer and keyboard activation alike. The URLs belong to the demand source and are sent as given, with nothing read back. Most ads carry none. For a layout you render yourself, trackRender and trackImpression send theirs as before, and the new sdk.trackClick(ad) sends the ones a click owes; sdk.trackTap(ad, tap) sends them too, so a layout already reporting taps needs no change. Each notice goes out once per showing. See Rendering Ads and the API Reference.
  • The SDK names itself to the ad server. Every request carries X-Elo-SDK: EloWebSDK/0.6.0, which is how the ad server knows this build sends demand-source notices and stops sending them itself. Expect the header if you inspect or proxy the SDK’s requests.
View on npm
  • Tap analytics for Elo-served ads. <EloAd> reports every click inside the card to POST /v1/sdk/events: the region under the pointer (thumbnail, headline, description, CTA, chevron, or the card’s own padding), the position as a fraction of the card’s size, the card’s size, whether the click opened the destination, the time since the impression, and the click’s index within the showing. Coordinates are relative to the card, never the page or the screen. That is what makes a tap heatmap and a missed-call-to-action rate measurable. Nothing about how the card behaves changed: the click still navigates to ad.click_url in a new tab, and the ad server still counts it there. At most fifty taps are reported per showing, and a keyboard activation of the card link reports nothing, since it carries no position. If you render your own card, sdk.trackTap(ad, tap) does the same for your layout — see Rendering Ads and the API Reference. The iOS and Android SDKs ship the same reporting in their 0.5.0.
  • getTrackingTotals() gained a tap entry beside render and impression. It counts the analytics events, not clicks — the click itself is a browser navigation the SDK never observes. Unlike the other two, a failed tap event isn’t retried: one lost tap is a lost sample, not a lost impression.
  • Ad requests now say which surface they’re for. The request carries display_position: "card", so web showings group with the mobile card in reporting rather than landing in the ad server’s unknown bucket. The Web SDK renders one surface, so it reports it itself; there is no parameter to pass.
View on npm
  • An image-only creative no longer gets an invented description. A creative with artwork but no description used to render the SDK’s own copy, Click to learn more →. Call-to-action copy is backend-managed, so the SDK writes none of its own: such a creative now renders its headline and nothing beneath it, with the trailing chevron still signalling that the card is the link. iOS dropped the same fallback in its 0.4.0 release and Android never had one, so all three SDKs now agree. If you relied on the nudge, set a description on the creative or render the card yourself with trackRender/trackImpression.
View on npm
  • New sdk.setUserData(data): publishers who know their signed-in user can share age, gender, email, and phone with ad requests. Contact details travel over HTTPS and are SHA-256 hashed at the ad server before anything is stored, so you don’t hash them yourself and Elo never persists a plain email address or phone number. The fields are recorded for upcoming targeting features and have no effect on ad selection today. Memory-only like setUserIdentifier: re-set per page load and clear on sign-out. The server discards user data entirely on requests flagged COPPA or TFUA, and on any request where GDPR applies. See the API Reference and Privacy & Consent.
  • Ads can carry a CTA button. A creative now carries an optional cta_text from the demand source (e.g. Install, Join the Club), which <EloAd> renders as a filled capsule in the card’s trailing slot. The whole card stays the click target, so the button is an affordance rather than a second link. Style it with the new .elo-ad-cta and .elo-ad-chevron hooks — see Rendering Ads.
  • The card no longer clips copy. Title, description, and CTA label each wrap to as many lines as they need, so the card’s height follows the creative. A creative with artwork but no description shows the same Click to learn more → nudge the mobile cards use.
View on npm
  • New sdk.trackRender(ad) / sdk.trackImpression(ad): render the ad yourself and still report it. Both are safe to call on every render pass — the one-render-one-impression-per-ad-opportunity limit now sits behind these methods rather than inside <EloAd>, so a hand-rolled card gets the same guarantee instead of having to hit the tracking URLs directly. Each resolves true only when the ad server confirmed the ping. sdk.hasTrackedImpression(ad) tells a custom layout whether an opportunity has already impressed, so it can skip arming its own dwell timer. See Rendering Ads. Nothing changes for <EloAd> users.
  • New ad.opportunity_id: the ad now carries its opportunity as well as its creative. opportunity_id is this showing — one per serve, and what the ad server keys render, impression, and click on; ad_id is the creative, stable across showings. Correlate delivery on opportunity_id, group by ad_id. Additive: nothing was renamed.
  • New sdk.getTrackingTotals(): attempted, delivered, failed, and inFlight per event since the last init(). failed sizes how many pings the ad server never confirmed.
  • An ad card no longer stays without its image when the same creative comes back in a later ad. A failed image load was remembered against the image, so in a chat where a fresh ad replaces the previous one without the card unmounting, one failure suppressed the thumbnail on every later ad serving that creative. It now applies only to the ad it was recorded for.
  • Tracking before init() no longer burns the ad’s one render or impression. It sent nothing — there was no visitor or session to attribute it to — but still marked the opportunity counted, so the real ping could never follow. The SDK warns and leaves the budget unspent instead.
  • init() clears the tracking state. Re-initializing already started a new session, but the render/impression bookkeeping from the old one survived, where it could suppress an ad shown under the new session. Ads fetched before the re-init keep their pinned bid-time identity.
View on npm
  • New sdk.setUserIdentifier(identifier): sites with a sign-in can send their own user ID as visitor_id in place of the SDK’s anonymous ID, so delivery, frequency capping, and reporting follow the user rather than the browser. Memory-only; re-set per page load and clear on sign-out. See the API Reference.
  • The whole card is clickable. Clicks landing in the gaps between image, title, and description previously did nothing and recorded no click.
  • A creative that wins more than once now records a render and an impression every time it’s shown — tracking dedup is keyed on the ad opportunity, not the creative.
  • Render and impression delivery is confirmed: a ping only counts on a 2xx response, and a failed ping retries the next time the ad mounts or becomes viewable.
  • An ad image that fails to load hides the thumbnail instead of showing a broken tile, and the X-Elo-State header encodes UTF-8 safely for non-Latin-1 identifiers.
Breaking changes View on npm
View on npm

Initial release as @growl/web-sdk: init() with visitor/session identity and IAB consent reading (TCF, GPP, COPPA/TFUA), fetchAds() against the Elo ad server, and the React card with automatic render and viewable-impression tracking (≥50% visible for 1 second).