Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Third Party Hell
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Matthias Le Brun
March 28, 2018
Technology
590
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Third Party Hell
Matthias Le Brun
March 28, 2018
More Decks by Matthias Le Brun
See All by Matthias Le Brun
GraphQL, Pothos & SQLite: a perfect match
bloodyowl
0
130
(why the hell did I) build a GraphQL client for the browser
bloodyowl
0
160
Boxed: bringing algebraic types to TypeScript
bloodyowl
0
210
leveraging (algebraic data) types to make your UI rock @ jsheroes
bloodyowl
0
350
Leveraging (algebraic data) types to make your UI rock solid
bloodyowl
0
530
La drôle d'histoire de JavaScript
bloodyowl
0
420
Healthy Code Collaboration
bloodyowl
0
390
Simplify your UI management with (algebraic data) types
bloodyowl
0
870
Simplify your UI management with (algebraic data) types
bloodyowl
1
600
Other Decks in Technology
See All in Technology
SQL Server 2025 最適化されたロック
odashinsuke
0
110
人にやさしく、AIにやさしく、書き手を選ばないIaCのガードレール再考 / Rethinking IaC Guardrails for Humans and AI Alike
kohbis
5
1.9k
HolmesGPTで始めるSREエージェント入門!プラットフォームの障害調査はAIにお任せ 〜
sanghyuk
0
250
キャリアLT今日までそして明日から
kentapapa
1
140
IR Today: Theory, Practice, and Agents
dtunkelang
0
300
Incremental HTTP
kazuho
5
1.8k
覗いてみよう 関数型ビジュアル言語×2Dグラフィックスの世界
yohyamasaki
0
160
2026-10-01_MagicPod_QAハーネスエンジニアリングとQA組織の未来像
ynisqa1988
0
110
Claude Designがめちゃくちゃ便利なので使ってほしい
diggymo
0
170
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
500
Apache Iceberg が拓く AI 時代のオープンレイクハウス
tomtanaka
0
200
AIに書かせて、プラットフォームで縛る ― EKSプラットフォームで実践した責任境界と権限設計
elmodev09
1
1.1k
Featured
See All Featured
Speed Design
sergeychernyshev
33
2.1k
Done Done
chrislema
187
17k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
420
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.2k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
310
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
290
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
440
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
390
Transcript
Third-party hell Making code for hostile environments
Matthias Le Brun @bloodyowl Be
third-party?
First party page You
None
use cases: widgets, players
not your page not your domain not controlled
strategy?
Inject DOM elements in the first party page?
First party CSS resets & defaults will fuck your page
up in unexpected ways
What you wrote Nice Nice What shows up Nice Nice
-> Nice Nice
Inline styles or ensure your stylesheet is always last in
the DOM
• unset all properties • unset all pseudo elements properties
• unset weird vendor selectors (some use them) You need to:
Alpha() AlphaImageLoader() :active additive-symbols (@counter-style) !::after (:after) align-content align-items align-self
all <an-plus-b> <angle> animation animation-delay animation-direction animation-duration animation-fill-mode animation-iteration-count animation-name animation-play-state animation-timing- function @annotation annotation() attr() Barn() BasicImage() BlendTrans() Blinds() Blur() !::backdrop backface-visibility background background-attachment background-blend-mode background-clip background-color background-image background-origin background-position background-repeat background-size <basic- shape> !::before (:before) <blend-mode> block-size blur() border border-block-end border-block-end-color border-block-end-style border-block-end-width border-block-start border-block-start-color border-block-start-style border-block-start-width border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width border-collapse border-color border-image border-image-outset border-image-repeat border- image-slice border-image-source border-image-width border-inline-end border-inline-end-color border-inline-end-style border-inline-end-width border-inline- start border-inline-start-color border-inline-start-style border-inline-start-width border-left border-left-color border-left-style border-left-width border-radius border-right border-right-color border-right-style border-right-width border-spacing border-style border-top border-top-color border-top-left- radius border-top-right-radius border-top-style border-top-width border-width bottom @bottom-center box-decoration-break box-shadow box-sizing break-after break-before break-inside brightness() CheckerBoard() Chroma() Compositor() calc() caption-side caret-color ch @character-variant character-variant() @charset :checked circle() clear clip clip-path cm <color> color column-count column-fill column-gap column-rule column-rule-color column-rule-style column- rule-width column-span column-width columns content contrast() <counter> counter-increment counter-reset @counter-style cross-fade() cubic-bezier() !::cue cursor <custom-ident> DropShadow() :default deg :dir direction :disabled display dpcm dpi dppx drop-shadow() Emboss() Engrave() element() ellipse() em :empty empty-cells :enabled ex Fade() FlipH() FlipV() fallback (@counter-style) filter <filter-function> :first :first-child !::first-letter (:first- letter) !::first-line (:first-line) :first-of-type fit-content() <flex> flex flex-basis flex-direction flex-flow flex-grow flex-shrink flex-wrap float :focus font @font-face font-family font-family (@font-face) font-feature-settings font-feature-settings (@font-face) @font-feature-values font-kerning font- language-override font-size font-size-adjust font-stretch font-stretch (@font-face) font-style font-style (@font-face) font-synthesis font-variant font- variant (@font-face) font-variant-alternates font-variant-caps font-variant-east-asian font-variant-ligatures font-variant-numeric font-variant-position font-variation-settings (@font-face) font-weight font-weight (@font-face) format() format() (@font-face) fr frames() <frequency> :fullscreen Glow() Gradient() GradientWipe() Gray() grad <gradient> grayscale() grid grid-area grid-auto-columns grid-auto-flow grid-auto-rows grid-column grid-column-end grid-column-gap grid-column-start grid-gap grid-row grid-row-end grid-row-gap grid-row-start grid-template grid-template-areas grid-template-columns grid- template-rows Hz hanging-punctuation height height (@viewport) @historical-forms :hover hsl() hsla() hue-rotate() hyphens ICMFilter() Inset() Invert() Iris() <ident> <image> image() image-orientation image-rendering image-resolution image-set() @import in :in-range :indeterminate inherit initial inline- size inset() <integer> :invalid invert() isolation justify-content kHz @keyframes Light() :lang :last-child :last-of-type leader() :left left @left-bottom <length> letter-spacing line-break line-height linear-gradient() :link list-style list-style-image list-style-position list-style-type local() MaskFilter() Matrix() MotionBlur() margin margin-block-end margin-block-start margin-bottom margin-inline-end margin-inline-start margin-left margin-right margin-top mask mask-clip mask-composite mask-image mask-mode mask-origin mask-position mask-repeat mask-size mask-type matrix() matrix3d() max-height max-height (@viewport) max-width max-width (@viewport) max-zoom (@viewport) @media min-block-size min-height min-height (@viewport) min-inline-size min-width min-width (@viewport) min-zoom (@viewport) minmax() mix-blend-mode mm ms ms-filter-alpha() ms-filter-basicimage() ms-filter-blendtrans() ms-filter-blur() ms-filter- chroma() ms-filter-compositor() ms-filter-dropshadow() ms-filter-emboss() ms-filter-engrave() ms-filter-fliph() ms-filter-flipv() ms-filter-glow() ms- filter-gray() ms-filter-icmfilter() ms-filter-invert() ms-filter-light() ms-filter-maskfilter() ms-filter-matrix() ms-filter-motionblur() ms-filter- redirect() ms-filter-revealtrans() ms-filter-shadow() ms-filter-wave() ms-filter-xray() ms-proceduralsurface-alphaimageloader() ms-proceduralsurface- gradient() ms-transition-barn() ms-transition-blinds() ms-transition-checkerboard() ms-transition-fade() ms-transition-gradientwipe() ms-transition-inset() ms-transition-iris() ms-transition-pixelate() ms-transition-radialwipe() ms-transition-randombars() ms-transition-randomdissolve() ms-transition-slide() ms- transition-spiral() ms-transition-stretch() ms-transition-strips() ms-transition-wheel() ms-transition-zigzag() @namespace negative (@counter- style) :not :nth-child :nth-last-child :nth-last-of-type :nth-of-type <number> object-fit object-position offset-block-end offset-block-start offset-inline- end offset-inline-start :only-child :only-of-type opacity opacity() :optional order orientation (@viewport) @ornaments ornaments() orphans :out-of-range outline outline-color outline-offset outline-style outline-width overflow overflow-wrap overflow-x overflow-y Pixelate() pad (@counter-style) padding padding-block-end padding-block-start padding-bottom padding-inline-end padding-inline-start padding-left padding-right padding-top @page page-break-after page-break-before page-break-inside pc <percentage> perspective perspective() perspective-origin place-content !::placeholder pointer-events polygon() <position> position prefix (@counter-style) pt px Q quotes RadialWipe() RandomBars() RandomDissolve() Redirect() RevealTrans() rad radial-gradient() range (@counter-style) <ratio> :read-only :read-write rect() rem repeat() repeating-linear-gradient() repeating-radial-gradient() :required resize <resolution> revert rgb() rgba() :right right @right-bottom :root rotate() rotate3d() rotateX() rotateY() rotateZ() ruby-align ruby-merge ruby-position Shadow() Slide() Spiral() Stretch() Strips() s saturate() scale() scale3d() scaleX() scaleY() scaleZ() :scope scroll-behavior scroll-snap-coordinate scroll-snap-destination scroll-snap-type !::selection sepia() <shape> shape-image-threshold shape-margin shape-outside skew() skewX() skewY() speak-as (@counter-style) src (@font- face) steps() <string> @styleset styleset() @stylistic stylistic() suffix (@counter-style) @supports @swash swash() symbols (@counter-style) symbols() system (@counter-style) tab-size table-layout :target target-counter() target-counters() target-text() text-align text-align-last text-combine-upright text- decoration text-decoration-color text-decoration-line text-decoration-style text-emphasis text-emphasis-color text-emphasis-position text-emphasis-style text-indent text-justify text-orientation text-overflow text-rendering text-shadow text-transform text-underline-position <time> <timing-function> top @top- center touch-action transform transform-box <transform-function> transform-origin transform-style transition transition-delay transition-duration transition-property transition-timing-function translate() translate3d() translateX() translateY() translateZ() turn unicode-bidi unicode-range (@font-face) unset <url> url() user-zoom (@viewport) :valid var() vertical-align vh @viewport visibility :visited vmax vmin vw Wave() Wheel() white-space widows width width (@viewport) will-change word-break word-spacing word-wrap writing-mode Xray() Zigzag() z-index zoom (@viewport) #--* NOPE
you need isolation
Inject DOM elements in the first party page?
Web Components?
scoped styles isolation
Not enough browser support + unstable when it works
Web Components?
iframe?
if you have a fixed ratio or height? sure
iframe adds two requests (HTML + inner JS) and limited
for communication
iframe?
sourceless iframe?
just use the iframe as a rendering target
let iframe = document.createElement("iframe"); iframe.src = "javascript:;";
Browser issues • IE can't access contentWindow without a domain
• Firefox doesn't always fire a load event
iframe.src = isTrident ? "javascript:" + `'<script> window.onload = function()
{ document.domain = "first-party.domain" } %</script>'` : "javascript:;";
setTimeout( renderWithoutLoadEvent, ARBITRARY_TIMEOUT );
an iframe has a fixed height Design issue
you need a JS running on the first party to
set the iframe height
watch the iframe body size?
body content content iframe
watch the iframe body size?
watch a container div in the body size
let lastHeight = 0; function tick() { let height =
root.getBoundingClientRect().height; if(height ##!== lastHeight) { lastHeight = height; iframe.style.height = height + "px"; } requestAnimationFrame(tick); } requestAnimationFrame(tick);
Try not to use global window & document
node.ownerDocument document.defaultView Use these
arrayFromIframe instanceof Array Array.isArray(arrayFromIframe) ({}).toString.call(arrayFromIframe) !!=== "[object Array]" Don’t trust
inheritance
Layers? Modals?
Dropdown ▼
Dropdown ▼ solution 1: expand iframe contents of the first-party
page
Dropdown ▼ solution 2: scroll view
Dropdown ▼ solution 3: more iframes™ r + pageYOffset
let layerManager: (module LayerManager) = environment )== "THIRD_PARTY" ? ((module
ThirdPartyLayerManager): (module LayerManager)) : ((module DefaultLayerManager): (module LayerManager)); module LayerManager = (val layerManager);
ReactDOM.createPortal
No persistent storage No service workers ...
SDK needs to be small
no (or very few) polyfills
Can't break MooTools or Prototype.js
Bundler conflicts { +/* !!... #*/ output: { +/* !!...
#*/ jsonpFunction: "namespaced__define", } }
Booting
domReady?
when DOMContentLoaded or load fire, you don't know if your
booting script is ready
async loop
function checkSdk() { if(window.myBootingFunction) { window.myBootingFunction() } else { setTimeout(checkSdk,
40) } } checkSdk()
third-party analytics?
(function(_, b, e, o, p) { if (_.myTracker) { return;
} _.myTracker = function myTracker() { myTracker.events.push([].slice.call(arguments)); }; myTracker.events = []; o = b.createElement(e); o.src = "https:///example.com/path-to-real-script.js"; p = b.querySelector(e); p.parentNode.insertBefore(o, p); })(window, document, "script");
register events before your actual script has loaded
If you're going to make a third-party widget: keep all
that in mind
the code you made your client install on their page
needs to work forever
you can only add non-breaking changes
tl;dr; styles: you're fucked scripts: you're fucked API: no breaking
change
Thank you Got any questions? ✋