Skip to content
  • There are no suggestions because the search field is empty.

Targeting Experiments with Dynamic Location Triggers (JS Callbacks)

Important Update: Guidance on Targeting Experiments and Firing Goals Using JavaScript Conditions

Author George F. Crew

IN THIS ARTICLE YOU WILL:

To provide better performance and more reliable experiment activation, Convert is deprecating the legacy tokens convert_recheck_experiment() and convert_recheck_experience().

Instead, users should now use Dynamic Location Triggers with a Callback type. This allows you to wait for specific conditions—like a DOM element appearing or a Data Layer value being populated—before your experiment fires.

The Strategy: Global Utility + Location Callback

The most efficient way to implement this is to define a "wait" utility function in your Project Global JS and then call that function within your specific Experiment Location Callback.

Use Case 1: Activating when an Element is Present

Use this when your target element isn't available immediately (common in Single Page Applications or elements that load after a delay).

1. Add to Project Global JS

First, add this reusable helper function to your Project settings so it’s available across all experiments:

window.waitFor = (
  selector,
  {
    scope = document,
    nextRetry = 100, // ms
    maxRetries = 50,
  } = {}
) => {
  let retries = 0;
  const check = (resolve) => {
    const result = scope?.querySelector?.(selector);
    if (result) {
      resolve(result);
    } else if (retries < maxRetries) {
      retries++;
      setTimeout(() => check(resolve), nextRetry);
    } else {
      resolve();
    }
  };
  return new Promise((resolve) => check(resolve));
};

2. Add to Location Callback JS

In your Experiment's Location settings, choose JS Callback as the trigger type and use the following:

if (options.isActive) return;

window.waitFor("ELEMENT_SELECTOR").then((element) => {
  if (element) {
    activate();
  }
});

(Replace ELEMENT_SELECTOR with your specific CSS selector, e.g., .checkout-button)


Use Case 2: Activating based on a Data Layer Property

This is the preferred method for Shopify stores or sites using GTM where you need to wait for a specific event (like checkout_started) to appear in the window.dataLayer.

1. Add to Project Global JS

Add this function to your Project settings:

window.waitForDataLayer = (
  key,
  value,
  {
    nextRetry = 100, // ms
    maxRetries = 50,
  } = {}
) => {
  let retries = 0;
  const check = (resolve) => {
    const result = window?.dataLayer?.find((layer) => layer[key] === value);
    if (result) {
      resolve(result);
    } else if (retries < maxRetries) {
      retries++;
      setTimeout(() => check(resolve), nextRetry);
    } else {
      resolve();
    }
  };
  return new Promise((resolve) => check(resolve));
};

2. Add to Location Callback JS

In your Experiment's Location settings, use this callback:

if (options.isActive) return;

window.waitForDataLayer("KEY", "VALUE").then((element) => {
  if (element) {
    activate();
  }
});

(Replace KEY and VALUE with your specific event details, e.g., "event" and "checkout_started")


Why Use This Method?

  • Performance: It uses a "retry" loop with a timeout rather than constant polling, reducing CPU overhead.
  • Reliability: By using activate(), you ensure the experiment only runs when the page is actually ready for the change.
  • Flexibility: Once the utility functions are in your Global JS, setting up new triggers for different experiments takes seconds.

Note: Ensure your site's Data Layer or elements usually load within the maxRetries window (5 seconds by default). You can increase the maxRetries in the code if your site has particularly slow asynchronous loading.