Loading synchronous / document.write-ing ads asynchronously against their will in a React component
import React from 'react'; | |
import $script from 'scriptjs'; | |
require('postscribe/htmlParser/htmlParser.js'); // This is required for postScribe, postScribe is a bit annoying. | |
const postscribe = require('exports?postscribe!postscribe'); // Needs webpack exports-loader! Otherwise, just require it and use window.postscribe. | |
// This GlobalAdCodePromise is a simple promise that uses script.js to load a javascript file and then resolve. | |
const GlobalAdCodePromise = new Promise((resolve) => { | |
setTimeout(() => { | |
$script('http://annoying.adprovider.com/ad.js', () => { | |
resolve(window.annoyingAdProvider); | |
}); | |
}, 500); | |
}); | |
// If the ad provider base code uses document.write too, you can fix this with Postscribe too. | |
// The #ad-safe-container is a simple div I put somewhere in my HTML, the ad just needs a place to write to. | |
const DocumentWritingAdPromise = new Promise((resolve) => { | |
setTimeout(() => { | |
postscribe('#ad-safe-container', `<script src='http://cdn.adprovider.com/js/sync.js'></script>`, { | |
done: () => { | |
resolve(true); | |
} | |
}); | |
}, 500); | |
}); | |
class Ad extends React.Component { | |
constructor(...options) { | |
super(...options); | |
this.releaseTimeout = undefined; | |
this.state = { | |
released: false | |
}; | |
} | |
render() { | |
if (!this.state.released) { | |
return <div className='ad-placeholder' />; | |
} | |
return ( | |
<div ref='adcontainer'></div> | |
); | |
} | |
componentDidUpdate(prevProps, prevState) { | |
if (this.state.released && !prevState.released) { | |
let ad = this.getAdHtml(); | |
setImmediate(() => { | |
// debug('Requesting ad render'); | |
let element = React.findDOMNode(this.refs.adcontainer); | |
postscribe(element, ad, {done: () => { | |
// debug('Ad rendered'); | |
}}); | |
}); | |
} | |
} | |
getAdHtml() { | |
let ad = ( | |
<div id='square-ad-from-provider'> | |
<script type='text/javascript' dangerouslySetInnerHTML={`window.annoyingSyncAdProvider.tag({ format: "square-ad", publication: "mysite"});`}></script> | |
</div> | |
); | |
return React.renderToStaticMarkup(ad); | |
} | |
loadAd() { | |
// debug('Execute ad load'); | |
GlobalAdCodePromise.then(() => this.setState({released: true})); | |
} | |
componentDidMount() { | |
// debug('Request ad load'); | |
this.releaseTimeout = setTimeout(() => this.loadAd(), 500); | |
} | |
componentWillUnmount() { | |
if (this.op) { | |
clearTimeout(this.releaseTimeout); | |
} | |
} | |
} | |
export default Ad; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment