Custom JS Overview (for Developers)

Custom JS (Boxes) – Form Submission Functions

This document explains the Custom JS Execution “Pipeline”: how and when your various Custom JS runs, what input it receives, and what output is expected.

Some Custom JS functions at the box-level run exclusively as part of a synchronous form processing pipeline. The order of execution of these actions are indicated by the dropdown in the HQ, as well as outlined in order here. Some additional non-configurable execution steps happen automatically, and are indicated by the word “Native”:

1.  Native – get all form data from the HTML form fields and Editor settings, and compile this into a form data object to use for further processing.  No validation is performed at this point.  This is simply acquisition of data.

2.  Before Form Validation – return types:
boolean / false – halts execution of form submission, and does no further processing.
boolean / true – continue with standard/native validation and further processing.
string – run the “showError(message)” function, which will show a red error bubble with the string you returned.   Halts execution of form submission, and does no further processing.  This can be useful if you want to run your own validation on some fields before standard/native validation occurs.
object – all form data that reaches the processing pipeline for a submission is represented as a single object.  The entire form data object will be overwritten with the object you return here.  Note, this skips data validation, so it would be up to you to run your own validation.  If this is not acceptable, consider doing object modification in “After Form Validation” instead.
return; – returning undefined (or null, or a number, or anything else, or nothing at all) will not take any action on the form data.  Processing will continue with regular validation.

3.  Native – standard/native form validation runs if anything other than the following is returned from step 2 above:  false, string, object.  Standard/Native validation simply checks for any fields marked “required” in the Editor, validates the Email field.

4.  After Form Validation – return types:
boolean / false – halts execution of form submission, and does no further processing.
boolean / true – continue with further processing.
string – run the “showError(message)” function, which will show a red error bubble with the string you returned.   Halts execution of form submission, and does no further processing.  This can be useful if you want to run your own validation on some fields after standard/native validation occurs.
object – all form data that reaches the processing pipeline for a submission is represented as a single object.  The entire form data object will be overwritten with the object you return here.
return; – returning undefined (or null, or a number, or anything else, or nothing at all) will not take any action on the form data.  Processing will continue with regular validation.
Note:  If your goal is to modify the form data object, then you must return an object from either “Before Form Validation” or “After Form Validation”.  If you simply modify the object within your function, that is not enough.  You must then return that object after you modify it.  It is highly recommended that you do this in either “Before Form Validation” or “After Form Validation”.  If you wait to do it in “Before Form Submit” that can alter the query string that is built and sent to our backend for post-processing.  This would be a highly advanced procedure, mostly intended for internal staff to accomplish unanticipated use cases.  Furthermore, it is most likely redundant to return an object from both “Before Form Validation” and “After Form Validation”.  It is recommended to return an object from one or the other, if your goal is to modify the form data object.

Note:  If your goal is to modify the form data object, common practice is to use the current form data object, then modify it, then return it.  The current form data object can be referenced through the variable “x” which is passed to you as a reserved variable in all Custom JS (Boxes) functions.

5.  Native – showLoading() – this shows the loading animation which indicates to the user that their form is in the process of submitting.  If you really need to override this with an alternate loading animation, you can target “#modal_loading_spinner” in “After DOM Ready”.  We will consider adding more loading animation options in the future.

6.  Native –  Build internal query string for backend post-processing.  This is a combination of field metadata set in the Editor, and how that maps to specific data entered in the form (ie. the form object).

7.  Before Form Submit – return types:

boolean / false – halts execution of form submission, and does no further processing.
boolean / true – continue with submission of the form data to our backend for post-processing .
string – run the “showError(message)” function, which will show a red error bubble with the string you returned.   Halts execution of form submission, and does no further processing.  This can be useful if you want to run your own validation on some fields after standard/native validation occurs.
object – all form data that reaches the processing pipeline for a submission is represented as a single object.  The entire form data object will be overwritten with the object you return here.  Note: it is not recommended to return an object here.  Rather use “Before Form Validation” or “After Form Validation”.
return; – returning undefined (or null, or a number, or anything else, or nothing at all) will not take any action on the form data.  Processing will continue with submission of the form data to our backend for post-processing.

8.  Native –  Submission of the form data to our backend for post-processing.

9.  After Form Submit – return types:

boolean / false – halts execution of form submission, and does no further processing.
anything else, or nothing returned –  no action taken, continue with “after submit” action, as defined in the Editor.

10.  Native – Continue with “after form submit” action, as defined in the Editor (ie. change pages, redirect to url, etc).

11.  Native – hideLoading() – hides the loading animation

Custom JS (Boxes) – Inputs => (api, s, x)

Every Custom JS function receives the same 3 parameters as inputs (case sensitive):

1.  api – this allows you to exchange data easily between Custom JS (Parent) and Custom JS (Boxes).  For example, if you define “api.myCustomVar = true;” in Custom JS (Parent), then you will be able to detect the value of that variable simply by referencing it the same way in Custom JS (Boxes) “if (api.myCustomVar) return false;”.  Just note that this “api” variable exchange between Parent and Child is time/sequence dependent, just as you would expect.  So in this example, you may want to define “api.myCustomVar = true;” in Custom JS (Parent) – After Document Ready.  That will ensure that your custom var is defined and accessible by the time any box-level functions run in the child.

2.  x – this is the “form data object” and only contains data for “Before Form Validation”, “After Form Validation”, “Before Form Submit”, and “After Form Submit”.  For all other Custom JS (Boxes) functions, x will equal an object with no keys “{}”.

Important note about “x”!  If your goal is to modify the form data object, common practice is to use the current form data object, then modify it, then return it.  The current form data object can be referenced through the variable “x” which is passed to you as a reserved variable in all Custom JS (Boxes) functions, but only relevant for the “form processing functions” – Before/After Validation, and Before/After Submit.  For example, let’s say that in “Before Form Validation” you wanted to grab the domain from the email address, and pass that in the form data as “custom_7”.  You could use the following code for that:

if (x.email && x.email.indexOf("@") > 0) {
x.custom_7 = x.email.split("@")[1];
return x;
}

Since you are doing this in “Before Form Validation” it will skip standard/native validation of the email address (but only if you end up finding an email address with an @ symbol in it, and returning the modified object “x”).  On the other hand, if you don’t find a valid email with an @ symbol in it, then it will skip your custom object return, and will therefore run standard/native validation as though you never had any custom code written.  So in the above case, if you want standard/native email validation to always run first, simply move the above code snippet to “After Form Validation”.  Or use a combination of Before/After Form Validation as you see fit.

Notice how the variable “x” already contains “x.email” in the example above?  That is because “x” is an object that contains all the form data at this point.  We make all the form data available to you through the “x” object.  If you want to see what data is included in “x”, simply do a “console.log(x)” and trigger the lightbox to run and submit the form.  Then view the console to see what object properties are output (and therefore available to you).

Finally, note in the example above, that “custom_7” may not have originally been turned on in the Editor.  But you can add additional properties to the “x” object as you see fit, even if they were never turned on in the Editor.

3.  s – this is the object that contains most of the metadata about the lightbox being displayed, and will be provided for use in every Custom JS (Boxes) function.

  • s.protocol = PROTOCOL;
  • s.protocol_user_override = PROTOCOL_USER_OVERRIDE;
  • s.widget_type = WIDGET_TYPE;
  • s.digioh_cache_version = DIGIOH_CACHE_VERSION;
  • s.parent_url = PARENT_URL;
  • s.full_url = FULL_URL || ”;
  • s.use_bugsnag = DIGIOH_USE_BUGSNAG;
  • s.use_console = SHOW_ERRORS;
  • s.is_preview = IS_PREVIEW;
  • s.is_responsive = DIGIOH_USE_RESPONSIVE;
  • s.is_variation = IS_VARIATION;
  • s.user_id = VENDOR_GUID;
  • s.user_guid = VENDOR_GUID;
  • s.vendor_id = VENDOR_GUID;
  • s.vendor_guid = VENDOR_GUID;
  • s.lightbox_id = LIGHTBOX_GUID;
  • s.lightbox_guid = LIGHTBOX_GUID;
  • s.lightbox_short_id = LIGHTBOX_SHORT_ID;
  • s.lightbox_name = LIGHTBOX_NAME;
  • s.variation_id = VARIATION_GUID;
  • s.variation_guid = VARIATION_GUID;
  • s.variation_short_id = VARIATION_SHORT_ID;
  • s.variation_name = VARIATION_NAME;
  • s.lightbox_or_variation_id = LIGHTBOX_OR_VARIATION_GUID;
  • s.lightbox_or_variation_guid = LIGHTBOX_OR_VARIATION_GUID;
  • s.lightbox_or_variation_short_id = (IS_VARIATION ? VARIATION_SHORT_ID : LIGHTBOX_SHORT_ID);
  • s.lightbox_or_variation_name = (IS_VARIATION ? VARIATION_NAME : LIGHTBOX_NAME);
  • s.is_desktop = IS_DESKTOP;
  • s.is_phone = IS_PHONE;
  • s.is_tablet = IS_TABLET;
  • s.is_mobile = IS_MOBILE;
  • Custom JS (Boxes) – On/Off & Include/Exclude

1. Include Box IDs – enter a single Box Short ID (ex: 123456), or multiple Box Short IDs separated by a comma.  If one or more valid IDs are entered here, then this function will run for ONLY these boxes, and no other boxes.

2. Exclude Box IDs – enter a single Box Short ID (ex: 123456), or multiple Box Short IDs separated by a comma.  If one or more valid IDs are entered here, then this function will run for EVERY box EXCEPT these boxes defined here.

3. Include/Exclude Function – the purpose of this function is to write logic based on the metadata that determines whether or not the Custom JS snippet should run for the box in question.  The Include/Exclude function receives the same inputs (api, s, x) as the regular Custom JS function would receive, and these inputs are defined above.  If you “return true;” from the Include/Exclude function, then the Custom JS snippet will run.  “return false;” and the Custom JS snippet will NOT run.  You could use this to conditionally run a Custom JS snippet only on MOBILE, for example:  return s.is_mobile;

4. Toggle the “ON/OFF” switch to set your code snippet eligibility.  If you toggle it to the “OFF” position, then that code snippet will never run, no matter what (as long as you published after you turned it “OFF”).  Otherwise, if it is in the “ON” position, then the code snippet is eligible to run, based on the Include/Exclude rules you defined.

_________________________________________________________________

Custom JS (Parent)

Common Input Parameters: (window, document, jQuery, api)

1. window – this is the outermost parent window context, under which the main website is functioning.

2. document – this is the outermost parent window’s document context, under which the main website is functioning.

3. jQuery – this is DIGIOH’s private jQuery context, which is completely separate from the parent window’s jQuery context.  We use our own private jQuery context to ensure cross-site consistency of jQuery versioning in our platform.  It also prevents jQuery conflicts with the parent website.  You can also reference it the following 3 ways:  “jQuery”, “$”, or “JQUERY_DIGIOH”

Note: if you need to hook into the parent window’s jQuery context for any particular reason (ie. event listeners), you can do so as follows:  “parent.jQuery”

4. api – use this to pass data back and forth between Custom JS (Parent) and Custom JS (Boxes).  You can use this object to define custom functions and/or variables to use platform-wide, as you see fit.  This “api” object also contains reference to our native functions which you can find under the following namespace: api.LIGHTBOX

The following native functions are available under advanced use cases (WARNING: USE WITH CAUTION, we cannot provide support if the below functions are misused).  Many of these (but not all) require you to pass the “lightbox_id” value as a single input parameter:

api.LIGHTBOX.loadLightbox = loadLightbox;
api.LIGHTBOX.closeSidebar = closeSidebar;
api.LIGHTBOX.getLightboxDomId = getLightboxDomId;

api.LIGHTBOX.cloneObj = cloneObj;

api.LIGHTBOX.isPhone = isPhone;
api.LIGHTBOX.isTablet = isTablet;
api.LIGHTBOX.isMobile = isMobile;
api.LIGHTBOX.isDesktop = isDesktop;
api.LIGHTBOX.isiOs = isiOs;

api.LIGHTBOX.getActualBoxWidthAndHeight = getActualBoxWidthAndHeight;
api.LIGHTBOX.getBoxWidth = getBoxWidth;
api.LIGHTBOX.getBoxHeight = getBoxHeight;
api.LIGHTBOX.getResponsiveBoxWidth = getResponsiveBoxWidth;
api.LIGHTBOX.getResponsiveBoxHeight = getResponsiveBoxHeight;
api.LIGHTBOX.getResponsiveBoxWidthPercent = getResponsiveBoxWidthPercent;
api.LIGHTBOX.getResponsiveBoxHeightPercent = getResponsiveBoxHeightPercent;
api.LIGHTBOX.getResponsiveBoxWidthMax = getResponsiveBoxWidthMax;
api.LIGHTBOX.getResponsiveBoxHeightMax = getResponsiveBoxHeightMax;
api.LIGHTBOX.getResponsiveBoxWidthMin = getResponsiveBoxWidthMin;
api.LIGHTBOX.getResponsiveBoxHeightMin = getResponsiveBoxHeightMin;

api.LIGHTBOX.tryLoadGeoIp = tryLoadGeoIp;

api.LIGHTBOX.sendMessageToIframe = sendMessageToIframe;
api.LIGHTBOX.receiveMessageFromIframe = receiveMessageFromIframe;
api.LIGHTBOX.relayMessageToIframe = relayMessageToIframe;

api.LIGHTBOX.setLightboxID = setLightboxID;
api.LIGHTBOX.hasOpenLightboxes = hasOpenLightboxes;
api.LIGHTBOX.closeAllOpenLightboxes = closeAllOpenLightboxes;

api.LIGHTBOX.initExistsSelectors = initExistsSelectors;
api.LIGHTBOX.recheckExistsSelectors = recheckExistsSelectors;
api.LIGHTBOX.addExistsSelector = addExistsSelector;
api.LIGHTBOX.removeExistsSelector = removeExistsSelector;
api.LIGHTBOX.getExistsSelectors = getExistsSelectors;

api.LIGHTBOX.checkConditions = checkConditions;
api.LIGHTBOX.checkConditionsClick = checkConditionsClick;
api.LIGHTBOX.checkConditionsHover = checkConditionsHover;
api.LIGHTBOX.checkConditionsScroll = checkConditionsScroll;
api.LIGHTBOX.checkConditionsExit = checkConditionsExit;
api.LIGHTBOX.checkConditionsLoad = checkConditionsLoad;
api.LIGHTBOX.checkConditionsTime = checkConditionsTime;

api.LIGHTBOX.isInlineLightbox = isInlineLightbox;
api.LIGHTBOX.embedInlineLightboxForm = embedInlineLightboxForm;
api.LIGHTBOX.reDisplayInlineForm = reDisplayInlineForm;

api.LIGHTBOX.onInfiniteScrollPageChanged = onInfiniteScrollPageChanged;

api.LIGHTBOX.INTEGRATION_MAP = {};

After Document Ready
inputs: api, window, document, jQuery
output: return false, and only eligible “inline” boxes will be displayed.  This is based on whether you set each particular “inline” box to “Display If Conditions Pass” or “Always Display” in the Editor.  Only “Always Display” boxes will be displayed if you “return false;” from “After Document Ready” here.  Otherwise, if you don’t return anything, or return anything other than false, nothing special will happen and processing will continue on as normal.  The next step that executes in the processing pipeline is that we will set the Conditions for all eligible lightboxes.  All analytics variables will have been set by this time, and available to you through the following global object variable:  DIGIOH_LIGHTBOX_ANALYTICS

Before Lightbox Display
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  return false, and the lightbox in question will NOT BE DISPLAYED.  return true (or nothing, or anything else) and the lightbox will be displayed normally.

After Lightbox Display
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  no need to return anything, as it will do nothing here.

After Lightbox Submit
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  no need to return anything, as it will do nothing here.
Note: see below for more info on accessing form data from within this function.

After Lightbox Redirect
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  no need to return anything, as it will do nothing here.

After Lightbox Download
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  no need to return anything, as it will do nothing here.

After Lightbox Close
inputs:  api, window, document, jQuery, lightbox_id, variation_id – includes all the common variables (api, window, document, jQuery,) plus the additional 2 variables:  lightbox_id is the 32 character GUID.  variation_id will only exist if the lightbox in question is a variation.
output:  no need to return anything, as it will do nothing here.

Custom JS (Parent) – After Lightbox Submit – Accessing Form Data
Here is some custom code you can use to acquire form values from within that function specifically:

var myObj = {};

if (typeof DIGIOH_LIGHTBOX_NAMES !== 'undefined' && DIGIOH_LIGHTBOX_NAMES.hasOwnProperty(lightbox_id)) {
myObj.lightbox_name = DIGIOH_LIGHTBOX_NAMES[lightbox_id];
} else {
myObj.lightbox_name = '';
}

if (typeof DIGIOH_LIGHTBOX_ANALYTICS !== 'undefined' && DIGIOH_LIGHTBOX_ANALYTICS.hasOwnProperty('form_submit_data')) {
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('email') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.email) myObj.email = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.email;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('first_name') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.first_name) myObj.first_name = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.first_name;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('last_name') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.last_name) myObj.last_name = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.last_name;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('phone') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.phone) myObj.phone = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.phone;

if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_1') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_1 !== null) myObj.custom_1 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_1;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_2') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_2 !== null) myObj.custom_2 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_2;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_3') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_3 !== null) myObj.custom_3 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_3;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_4') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_4 !== null) myObj.custom_4 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_4;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_5') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_5 !== null) myObj.custom_5 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_5;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_6') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_6 !== null) myObj.custom_6 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_6;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_7') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_7 !== null) myObj.custom_7 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_7;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_8') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_8 !== null) myObj.custom_8 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_8;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_9') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_9 !== null) myObj.custom_9 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_9;
if (DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.hasOwnProperty('custom_10') && DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_10 !== null) myObj.custom_10 = DIGIOH_LIGHTBOX_ANALYTICS.form_submit_data.custom_10;
}

if (typeof DIGIOH_LIGHTBOX_ANALYTICS !== 'undefined' && DIGIOH_LIGHTBOX_ANALYTICS.hasOwnProperty('VARS')) {
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('city') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.city) myObj.city = DIGIOH_LIGHTBOX_ANALYTICS.VARS.city;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('state') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.state) myObj.state = DIGIOH_LIGHTBOX_ANALYTICS.VARS.state;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('country') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.country) myObj.country = DIGIOH_LIGHTBOX_ANALYTICS.VARS.country;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('ip_address') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.ip_address) myObj.ip_address = DIGIOH_LIGHTBOX_ANALYTICS.VARS.ip_address;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('web_source') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.web_source) myObj.web_source = DIGIOH_LIGHTBOX_ANALYTICS.VARS.web_source;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('page_visits')) myObj.page_views = DIGIOH_LIGHTBOX_ANALYTICS.VARS.page_visits;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('past_visits')) myObj.past_visits = DIGIOH_LIGHTBOX_ANALYTICS.VARS.past_visits;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('device') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.device) myObj.device = DIGIOH_LIGHTBOX_ANALYTICS.VARS.device;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('browser_type') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.browser_type) myObj.browser = DIGIOH_LIGHTBOX_ANALYTICS.VARS.browser_type;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('operating_system') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.operating_system) myObj.operating_system = DIGIOH_LIGHTBOX_ANALYTICS.VARS.operating_system;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('landing_page') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.landing_page) myObj.landing_page_url = DIGIOH_LIGHTBOX_ANALYTICS.VARS.landing_page;
if (DIGIOH_LIGHTBOX_ANALYTICS.VARS.hasOwnProperty('current_page_url') && DIGIOH_LIGHTBOX_ANALYTICS.VARS.current_page_url) myObj.submit_page_url = DIGIOH_LIGHTBOX_ANALYTICS.VARS.current_page_url;
}

Other Info for Custom JS (Parent)
JQUERY_DIGIOH, jQuery, and $ – all 3 variables can be used to reference jQuery.
DIGIOH_CUSTOM_JS_GLOBAL – this is a globally scoped object that you can use to pass data between events (ready, display, submit, etc). Default Value = {}
DIGIOH_IS_PREVIEW – this is a globally scoped boolean variable that indicates wether the lightbox is in preview mode or not.
DIGIOH_CUSTOM_JS.log(‘some text’) – use this instead of using console.log() for cross-browser compatibility.
DIGIOH_COOKIE.set(name, value); (use this to set a cookie).
DIGIOH_COOKIE.get(name); (use this to get a cookie).
Analytics, Geo-location, Device, and Cookie data have all been set by this point.
Make sure to use ‘window’ and ‘document’ to prefix anything DOM related.
All custom JS code runs synchronously.
return false; to stop further execution of Digioh JS (After Doc Ready, Before Lightbox Display).
return true; (or don’t return at all) to continue with execution of Digioh JS (default).


 

Ability to abort display of a widget from within box-level JS, similar to what is possible with parent JS Before Display.

This can be implemented in Custom JS (Boxes) – Before DOM Ready.  This works just like in Custom JS (Parent), where you can “return false;” to terminate the box from Custom JS (Boxes) – Before DOM Ready.  This prevents the box from becoming constructed within Box-Level JS/HTML.  It also then sends a message to the parent to delete the Box iframe shell from the parent DOM, and updates a few variables to let them know this box no longer exists.  The key thing to know here, is that for termination to work, you must “return false;” at the end of your “Before DOM Ready” code.  If you return anything else, or just don’t return anything at all, then execution of the box will continue on normally.

*Special Note for Inline Boxes only:  once terminated by Custom JS (Boxes), the code marks the terminated box as “permanently terminated” for the pageview in question.  This prevents it from being displayed again in that pageview (but it could still be displayed on subsequent pageviews, so long as it is not terminated on those pageviews).

What is the difference between Before and After DOM ready? 

Before DOM Ready – runs immediately after jQuery is defined/scoped to the box, and after all “standard variables” have been defined and set to their final values (this is represented by the object “s” that is passed to all Custom JS Boxes functions).  These are the first 2 things that happen when the box iframe is created.After DOM Ready – runs after the above 2 things, and also after jQuery “document.ready” fires, and also after we finish constructing all the HTML for the box.  This is also the point at which we signal to the parent that the box is “ready for viewing”.

What is the logic behind on-page activation of Digioh. We know that it’s related to the DOM being ready, but exactly what it triggering the startup of Digioh? And at a high level, what happens before custom JS runs? I also noticed that the “Inline” version of the script seems to start up faster (before DOM ready?), what are the details of that?

Regarding “on-page” activation of Digioh, the “startup of Digioh” technically happens automatically and right away.  We use a private iframe to load Digioh in its own isolated window context.  This occurs immediately at the point the Digioh embed code is encountered, as the client’s website DOM starts loading.  Using a private window context allows us to actually start loading Digioh before the parent (ie. client’s website) has even finished loading.  So we could, for instance, have the client website owner add the Digioh embed code to the “<head>” section of their website.  This would get Digioh loading first, and is something I’d recommend, since it reduces the chance that another asset being loaded on your site that could block or slow the Digioh script from loading.  Just be careful, sometimes Digioh Custom JS depends on reading certain global variables from the client website’s native Javascript.  Therefore, it is typically safest to embed Digioh just before the closing “</head>” tag.

Once Digioh starts loading itself (which happens automatically) we take care of a few things that are not dependent on the parent DOM (like initializing our own libraries, getting the cookie storage system ready, etc), and then listen for the parent DOM to be ready before proceeding.  Then we initialize our analytics and events, get the lightbox effects ready, send the pageview analytics api call, and at the same time we get geo/device data back from our api as well.  Then, just prior to evaluating the Rules/Conditions, we run Custom JS (Parent) – After Doc Ready.  This is the only Custom JS function that is not tied to any box.

Just after Custom JS (Parent) – After Doc Ready runs, we build the Conditions-to-Box mapping, load past box activity from cookie data, initialize A/B Tests and Variations, setup responsive resizing, build all eligible Inline boxes, setup our jQuery selectors an listeners, and finally we check the Conditions to see if we have any eligible lightboxes.  The rest of the Custom JS functions are all box-related (Before Display, After Submit, etc), and not dependent on initial script execution.

Regarding the “inline” version of the script, it shouldn’t run any faster.  In fact, the function of the “inline” script is simply to load the regular version of the script (for run-time consistency, maintainability, and predictability we want to end up with a single end target script).  So if anything, the “inline” version should theoretically run fractionally slower.  That being said, I would say that the difference between “regular” and “inline” versions of the script would be negligible compared to “where” the script is being loaded on each respective website, and what other assets the site is loading. For example, is it being loaded in the “<head>” section, or the footer of the “<body>”?  Is it being loaded after many other assets on the site?  Is it an asset or media heavy site that tends to have a large amount of overall loading going on?  These are all things that are more likely to affect the perceived script loading speed.


Digioh supports asynchronous callbacks via Custom JS (Parent) – After Doc Ready.

1.  return “async_retry”;
When returning this specific string value from Custom JS (Parent) – After Doc Ready, Digioh will automatically try running Custom JS (Parent) – After Doc Ready again in 300 millisecond intervals.  It will continue doing so until a value other than “async_retry” is returned (or nothing is returned).
2.  return “async_callback”;
This allows you to determine when to re-run Custom JS (Parent) – After Doc Ready.  When you are ready for Custom JS (Parent) – After Doc Ready to resume, simply call the following function:
window.DIGIOH_API.LIGHTBOX.customJsOnDocumentReadyCallback();
Note: the above implementations will work best by using your own global JS variable flag, preferably set on the window object.  That can help your “Custom JS (Parent) – After Doc Ready” determine what “state” it is in.
For example, in Custom JS (Parent) – After Doc Ready, you may have the following code to determine the “state” of the application, and whether to proceed or do another retry/callback:
if (typeof window.is_file_set === 'undefined')
   return 'async_callback';
else if (window.is_file_set === null)
   return 'async_retry';
else {
   JQUERY_DIGIOH('body').append('<div id="file_was_set"></div>');
return true;
}
*Please note: the above retry/callback methods will completely halt execution of the Digioh javascript code.  Therefore, until you tell custom js to proceed, no conditions will be evaluated and no boxes will be displayed (including inline boxes).  This is by design, so you have time to completely determine your website state before proceeding with Digioh.
Aug. 20, 2018:
We just added a new function that indicates when Digioh has finished initializing (returns true/false):
window.DIGIOH_API.LIGHTBOX.isDigiohReady();
Oct. 29, 2018: