Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Emit onGPTScriptLoad error #192

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion js/dfpslotsprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default class DFPSlotsProvider extends React.Component {
mobileScaling: PropTypes.number,
}),
]),
onGPTScriptLoadError: PropTypes.func,
};

static defaultProps = {
Expand Down Expand Up @@ -82,8 +83,10 @@ export default class DFPSlotsProvider extends React.Component {
this.shouldReloadConfig = this.shouldReloadConfig.bind(this);
this.attachLoadCallback = this.attachLoadCallback.bind(this);
this.getContextValue = this.getContextValue.bind(this);
this.attachGPTLoadErrorCallback = this.attachGPTLoadErrorCallback.bind(this);
this.loadAlreadyCalled = false;
this.loadCallbackAttached = false;
this.gptLoadErrorCallbackAttached = false;
this.shouldReloadAds = false;
this.totalSlots = 0;
this.contextValue = {};
Expand All @@ -97,6 +100,8 @@ export default class DFPSlotsProvider extends React.Component {
if (this.props.autoLoad && !this.loadAdsIfPossible()) {
this.attachLoadCallback();
}

this.attachGPTLoadErrorCallback();
}

shouldComponentUpdate(nextProps) {
Expand Down Expand Up @@ -163,7 +168,6 @@ export default class DFPSlotsProvider extends React.Component {
DFPManager.configureSingleRequest(this.props.singleRequest);
DFPManager.configureDisableInitialLoad(this.props.disableInitialLoad);
DFPManager.configureLazyLoad(
!!this.props.lazyLoad,
typeof this.props.lazyLoad === 'boolean' ? null : this.props.lazyLoad,
);
DFPManager.setAdSenseAttributes(this.props.adSenseAttributes);
Expand All @@ -179,6 +183,18 @@ export default class DFPSlotsProvider extends React.Component {
return false;
}

attachGPTLoadErrorCallback() {
if (this.gptLoadErrorCallbackAttached === false) {
DFPManager.attachGPTLoadError(function handleGPTLoadError(data) {
if (this.props && this.props.onGPTScriptLoadError !== undefined) {
this.props.onGPTScriptLoadError(data);
}
});

this.gptLoadErrorCallbackAttached = true;
}
}

// pretty strait-forward interface that children ad slots use to register
// with their DFPSlotProvider parent node.
newSlotCallback() {
Expand Down
9 changes: 8 additions & 1 deletion js/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,10 @@ const DFPManager = Object.assign(new EventEmitter().setMaxListeners(0), {

getGoogletag() {
if (googleGPTScriptLoadPromise === null) {
googleGPTScriptLoadPromise = Utils.loadGPTScript();
googleGPTScriptLoadPromise = Utils.loadGPTScript()
.catch((error) => {
this.emit('gptScriptLoadError', { error });
});
}
return googleGPTScriptLoadPromise;
},
Expand Down Expand Up @@ -424,6 +427,10 @@ const DFPManager = Object.assign(new EventEmitter().setMaxListeners(0), {
return registeredSlots;
},

attachGPTLoadError(cb) {
this.on('gptScriptLoadError', cb);
},

attachSlotRenderEnded(cb) {
this.on('slotRenderEnded', cb);
},
Expand Down
122 changes: 64 additions & 58 deletions lib/adslot.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.AdSlot = void 0;
exports["default"] = exports.AdSlot = void 0;

var _react = _interopRequireDefault(require("react"));

Expand All @@ -13,60 +13,66 @@ var _manager = _interopRequireDefault(require("./manager"));

var _dfpslotsprovider = require("./dfpslotsprovider");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function () { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var dynamicAdCount = 0;

var AdSlot =
/*#__PURE__*/
function (_React$Component) {
var AdSlot = /*#__PURE__*/function (_React$Component) {
_inherits(AdSlot, _React$Component);

var _super = _createSuper(AdSlot);

function AdSlot(props) {
var _this;

_classCallCheck(this, AdSlot);

_this = _possibleConstructorReturn(this, _getPrototypeOf(AdSlot).call(this, props));
_this.doRegisterSlot = _this.doRegisterSlot.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.generateSlotId = _this.generateSlotId.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.getSlotId = _this.getSlotId.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.mapContextToAdSlotProps = _this.mapContextToAdSlotProps.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.slotShouldRefresh = _this.slotShouldRefresh.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.slotRenderEnded = _this.slotRenderEnded.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.slotRegisterCallback = _this.slotRegisterCallback.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.slotIsViewable = _this.slotIsViewable.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.slotVisibilityChanged = _this.slotVisibilityChanged.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.getClasses = _this.getClasses.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this = _super.call(this, props);
_this.doRegisterSlot = _this.doRegisterSlot.bind(_assertThisInitialized(_this));
_this.generateSlotId = _this.generateSlotId.bind(_assertThisInitialized(_this));
_this.getSlotId = _this.getSlotId.bind(_assertThisInitialized(_this));
_this.mapContextToAdSlotProps = _this.mapContextToAdSlotProps.bind(_assertThisInitialized(_this));
_this.slotShouldRefresh = _this.slotShouldRefresh.bind(_assertThisInitialized(_this));
_this.slotRenderEnded = _this.slotRenderEnded.bind(_assertThisInitialized(_this));
_this.slotRegisterCallback = _this.slotRegisterCallback.bind(_assertThisInitialized(_this));
_this.slotIsViewable = _this.slotIsViewable.bind(_assertThisInitialized(_this));
_this.slotVisibilityChanged = _this.slotVisibilityChanged.bind(_assertThisInitialized(_this));
_this.getClasses = _this.getClasses.bind(_assertThisInitialized(_this));
_this.state = {
slotId: _this.props.slotId || null,
className: _this.props.className || ''
};
_this.adElementRef = _react.default.createRef ? _react.default.createRef() : function (element) {
_this.adElementRef = _react["default"].createRef ? _react["default"].createRef() : function (element) {
_this.adElementRef = element;
};
return _this;
Expand Down Expand Up @@ -132,19 +138,19 @@ function (_React$Component) {
}, {
key: "doRegisterSlot",
value: function doRegisterSlot() {
_manager.default.registerSlot(_objectSpread({}, this.mapContextToAdSlotProps(), this.props, this.state, {
_manager["default"].registerSlot(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, this.mapContextToAdSlotProps()), this.props), this.state), {}, {
slotShouldRefresh: this.slotShouldRefresh
}));

if (this.props.fetchNow === true) {
_manager.default.load(this.getSlotId());
_manager["default"].load(this.getSlotId());
}

_manager.default.attachSlotRenderEnded(this.slotRenderEnded);
_manager["default"].attachSlotRenderEnded(this.slotRenderEnded);

_manager.default.attachSlotIsViewable(this.slotIsViewable);
_manager["default"].attachSlotIsViewable(this.slotIsViewable);

_manager.default.attachSlotVisibilityChanged(this.slotVisibilityChanged);
_manager["default"].attachSlotVisibilityChanged(this.slotVisibilityChanged);

this.slotRegisterCallback();
}
Expand All @@ -162,21 +168,21 @@ function (_React$Component) {
}, {
key: "unregisterSlot",
value: function unregisterSlot() {
_manager.default.unregisterSlot(_objectSpread({}, this.mapContextToAdSlotProps(), this.props, this.state));
_manager["default"].unregisterSlot(_objectSpread(_objectSpread(_objectSpread({}, this.mapContextToAdSlotProps()), this.props), this.state));

_manager.default.detachSlotRenderEnded(this.slotRenderEnded);
_manager["default"].detachSlotRenderEnded(this.slotRenderEnded);

_manager.default.detachSlotIsViewable(this.slotIsViewable);
_manager["default"].detachSlotIsViewable(this.slotIsViewable);

_manager.default.detachSlotVisibilityChanged(this.slotVisibilityChanged);
_manager["default"].detachSlotVisibilityChanged(this.slotVisibilityChanged);
}
}, {
key: "slotRenderEnded",
value: function slotRenderEnded(eventData) {
if (eventData.slotId === this.getSlotId()) {
if (this.props.onSlotRender !== undefined) {
// now that slot has rendered we have access to the ref
var params = _objectSpread({}, eventData, {
var params = _objectSpread(_objectSpread({}, eventData), {}, {
adElementRef: this.adElementRef
});

Expand Down Expand Up @@ -220,7 +226,7 @@ function (_React$Component) {
var r = true;

if (this.props.shouldRefresh !== undefined) {
r = this.props.shouldRefresh(_objectSpread({}, this.mapContextToAdSlotProps(), this.props, {
r = this.props.shouldRefresh(_objectSpread(_objectSpread(_objectSpread({}, this.mapContextToAdSlotProps()), this.props), {}, {
slotId: this.getSlotId()
}));
}
Expand All @@ -239,35 +245,35 @@ function (_React$Component) {
props.id = slotId;
}

return _react.default.createElement("div", {
return /*#__PURE__*/_react["default"].createElement("div", {
className: this.getClasses().join(' ').trim()
}, _react.default.createElement("div", _extends({
}, /*#__PURE__*/_react["default"].createElement("div", _extends({
ref: this.adElementRef
}, props)));
}
}]);

return AdSlot;
}(_react.default.Component);
}(_react["default"].Component);

exports.AdSlot = AdSlot;

_defineProperty(AdSlot, "propTypes", {
dfpNetworkId: _propTypes.default.string,
adUnit: _propTypes.default.string,
sizes: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.number), _propTypes.default.string])),
renderOutOfThePage: _propTypes.default.bool,
sizeMapping: _propTypes.default.arrayOf(_propTypes.default.object),
fetchNow: _propTypes.default.bool,
adSenseAttributes: _propTypes.default.object,
targetingArguments: _propTypes.default.object,
onSlotRender: _propTypes.default.func,
onSlotRegister: _propTypes.default.func,
onSlotIsViewable: _propTypes.default.func,
onSlotVisibilityChanged: _propTypes.default.func,
shouldRefresh: _propTypes.default.func,
slotId: _propTypes.default.string,
className: _propTypes.default.string
dfpNetworkId: _propTypes["default"].string,
adUnit: _propTypes["default"].string,
sizes: _propTypes["default"].arrayOf(_propTypes["default"].oneOfType([_propTypes["default"].arrayOf(_propTypes["default"].number), _propTypes["default"].string])),
renderOutOfThePage: _propTypes["default"].bool,
sizeMapping: _propTypes["default"].arrayOf(_propTypes["default"].object),
fetchNow: _propTypes["default"].bool,
adSenseAttributes: _propTypes["default"].object,
targetingArguments: _propTypes["default"].object,
onSlotRender: _propTypes["default"].func,
onSlotRegister: _propTypes["default"].func,
onSlotIsViewable: _propTypes["default"].func,
onSlotVisibilityChanged: _propTypes["default"].func,
shouldRefresh: _propTypes["default"].func,
slotId: _propTypes["default"].string,
className: _propTypes["default"].string
});

_defineProperty(AdSlot, "defaultProps", {
Expand All @@ -277,15 +283,15 @@ _defineProperty(AdSlot, "defaultProps", {
if (_dfpslotsprovider.Context === null) {
// React < 16.3
AdSlot.contextTypes = {
dfpNetworkId: _propTypes.default.string,
dfpAdUnit: _propTypes.default.string,
dfpSizeMapping: _propTypes.default.arrayOf(_propTypes.default.object),
dfpTargetingArguments: _propTypes.default.object,
newSlotCallback: _propTypes.default.func
dfpNetworkId: _propTypes["default"].string,
dfpAdUnit: _propTypes["default"].string,
dfpSizeMapping: _propTypes["default"].arrayOf(_propTypes["default"].object),
dfpTargetingArguments: _propTypes["default"].object,
newSlotCallback: _propTypes["default"].func
};
} else {
AdSlot.contextType = _dfpslotsprovider.Context;
}

var _default = AdSlot;
exports.default = _default;
exports["default"] = _default;
Loading