Skip to content

Instantly share code, notes, and snippets.

@Ambroos
Created April 29, 2015 14:18
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Ambroos/734933c4d3d11c3af847 to your computer and use it in GitHub Desktop.
Save Ambroos/734933c4d3d11c3af847 to your computer and use it in GitHub Desktop.
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