Advanced Concepts

Our JavaScript SDK supports a wide variety of custom use cases and can be tailored to fit the needs and goals of your company. Read about some of our more common advanced tagging scenarios.

Hosting your own CTA

If you don't want Extole to fill in the content for a CTA but you still want to make the area or text clickable to pop the Share Experience, complete the following steps.

Step 1
Navigate to the Marketing tab of the Campaign Editor in your My Extole account.

Step 2
Disable the toggle for "Serve Creative" to prevent Extole from injecting any content. (Since you are hosting the CTA creative on your end, you do not need to configure any of the creative variables.)

Step 3
Put HTML content onto your web page to display the CTA.

<span class="button" id="extole-header-placement">Refer and get $15</span>

Step 4
Insert the zone. Extole will not insert any content on the page, but will instead attach to the click event on the HTML element.

<script type="text/javascript">
  /* Start Extole */
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  /* End Extole */

   extole.createZone({
     name: 'global_header'
     element_id: 'extole-header-placement',     
  });
</script>

Sharing Product Details

When using a placement on your product page, Extole can automatically read in the OpenGraph tags on the page. This means that all you need to do for product sharing is place the standard Extole product tag.

If you do not have OpenGraph tags on the page (such as for a Single Page App) you need to pass the content information into Extole in the product tag.

Example product tag

<span id="extole_zone_product"></span>
<script type="text/javascript">
  /* Start Extole */
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  /* End Extole */

  extole.createZone({
    name: 'product',
    element_id: 'extole_zone_product',
    data: {
      "content": {
        "title":INSERT_DYNAMIC_DATA,
        "image_url":INSERT_DYNAMIC_DATA,
        "description":INSERT_DYNAMIC_DATA,
        "url":INSERT_DYNAMIC_DATA,
        "partner_content_id": INSERT_DYNAMIC_DATA
      }
    }
  });
</script>

The following table details the customer information that should be passed into the product tag.

Product Tag FieldDescription
content.titleThe title that appears for the content being shared.
content.image_urlA public URL for the image of the content being shared.
content.descriptionA description of the content.
content.urlThe URL of the content. When friends follow a share link, they will be taken back to the content URL instead of the campaign's default landing URL.
content.partner_content_idA unique identifier for the content (like an SKU). This is used to make sure a unique Share Link is created for each piece of content an advocate is sharing.

Sharing Behind Login

When you place CTAs for the Share Experience on pages where the advocate is logged in, you can pass additional profile information about the advocate into the request to personalize the experience.

Example my account tag

<span id="extole_zone_my_account"></span>
<script type="text/javascript">
  /* Start Extole */
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  /* End Extole */

   extole.createZone({
     name: 'my_account',
     element_id: 'extole_zone_my_account',
     data: {
       "first_name":INSERT_DYNAMIC_DATA,
       "last_name":INSERT_DYNAMIC_DATA,
       "email":INSERT_DYNAMIC_DATA,
       "partner_user_id":INSERT_DYNAMIC_DATA,
       "profile_picture":INSERT_DYNAMIC_DATA
     }
  });
</script>

The following table details the customer information that should be passed into the my account tag.

My Account Tag FieldDescription
first_name
recommended
The person's first name.
last_name
recommended
The person's last name.
email
required
The person's email address.
partner_user_id
recommended
This is your unique identifier, such as an account ID or member ID.

Embedding Stats Behind Login

If your referral experience is behind a login and you want to pass the user in a verified context to show embedded stats, this can be done with JWT. Learn about JWT and other ways for Verifying Consumers.

Example embedded stats

<script type="text/javascript">
  /* Start Extole */
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  /* End Extole */

   extole.createZone({
     name: 'embedded_stats'
     element_id: 'extole_zone_embedded_stats',
     jwt: '0000000000000000'
  });
</script>

Reporting Promotional Source

Extole tags will pass the promotional source of the tag for reporting analytics at Extole. For example, the global header tag would display in reporting as "Global Header."

It is possible, using tags, to pass in a promotional source that differs from the tag location. This could be used if a single tag, such as global_header, is used across multiple agent pages or store location pages and you wish to understand more details about the referral.

Example promotional source

<script type="text/javascript">
  /* Start Extole */
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  /* End Extole */

   extole.createZone({
     name: 'global_header'
     element_id: 'extole-header-placement',
     data: {
       "source":"store_760"
     }
  });
</script>

Displaying the Right Language

There are two ways to display the right language to your customers:

  1. Extole will read the browser settings of each user and display the correct language (if it exists).
  2. You can send in the exact language you want to be displayed for that user based on their selected preferences on your site. 

In order to pass the right language to display, you need to pass the locale in the zone tag or API call for the onsite CTA. The updated tag should look something like following example:

\<spanid="extole_zone_global_header"></span>

\<scripttype="text/javascript">

/_ Start Extole _/  
(function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||\[];a\<l.length;)k(l[a++],c[e])})  
(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);  
/_ End Extole _/

extole.createZone({ name: 'global_header', element_id: 'extole_zone_global_header',  
  data: {"locale":"en"}  
} }); </script>

When you pass the locale into the promotion or tag, that locale is stored on the user's profile for the next time they visit the site.

Multiple Countries, Languages & Currencies

If you are running a multi-national program that also has a unique offer or currency, you will want to use locale to specify the language as well as a label for the currency, through on the zone tag:

\<spanid="extole_zone_global_header"></span>

\<scripttype="text/javascript">

/_ Start Extole _/  
(function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||\[];a\<l.length;)k(l[a++],c[e])})  
(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);  
/_ End Extole _/

extole.createZone({ name: 'global_header', element_id: 'extole_zone_global_header',  
  data: {  
    "locale":"fr_FR";  
    "labels":"EU"  
} }); </script>

Tagging Single Page Apps & Progressive Web Apps

When developing with a single page app, the HTML of the page is being dynamically modified by JavaScript. In this case, instead of identifying the location of the Extole CTA using an HTML element ID (which can only work once), tags can pass in the JavaScript object of the element where the content should appear.

Example tag passing in JavaScript object

<span id="extole_zone_global_header"></span>
<script type="text/javascript">
  var headerPlacementElement = $("#extole_zone_global_header");
  
  <!-- Extole Magic Script -->
  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
  <!-- End Extole Magic Script -->

   extole.createZone({
     name: 'global_header',
     element: headerPlacementElement
  });
</script>

A similar example for ReactJS might look like this:

// For HTML Tag:
// <span id="extole_zone_global_header" ref={extoleRef}></span>

const extoleRef = useRef()
useEffect(() => {

  (function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);

  window.extole.createZone({name: "global_footer", element: extoleRef.current});
}

Encrypting Tag Data

Extole tags send information to your referral domain using SSL over AJAX requests. All information is encrypted in transit (under TLS) to Extole, followed by Extole encrypted information at rest using AES-256.

Extole tags do not support hashing of email addresses. Your program will normalize the email address against common fraud/quality issues (e.g., [email protected], [email protected]) as well as domain quality and requires access to the full and correct email address to automatically perform this normalization.

Extole only supports encryption at the transport layer. Your pages should load over SSL and tags will send the data to your program over SSL. Since all data utilized in the tags is data that is typically available for display on your website, there is no additional security exposure by only using transport-encryption.

Whitelisting Extole's Resources

If your site makes use of a Content Security Policy, you will need to add the Extole CDN domains and 3rd party domains that are utilized for scripts and content on your site.

Extole may utilize one of two CDN domains, either extole.io or xtlo.net. Both are listed in the following CSP.

CSP domains

default-src 'self' https://*.extole.io https://*.xtlo.net; 

style-src 'self' 'unsafe-inline' https://*.extole.io https://*.xtlo.net https://fonts.googleapis.com https://api.cloudsponge.com;

font-src 'self' https://*.extole.io https://*.xtlo.net https://fonts.gstatic.com https://api.cloudsponge.com;

script-src 'self' 'unsafe-eval' 'unsafe-inline' https://*.extole.io https://*.xtlo.net https://api.cloudsponge.com; 

connect-src 'self' https://*.cloudsponge.com https://*.extole.io https://*.xtlo.net;

img-src 'self' https://*.extole.io https://*.xtlo.net data: https://api.cloudsponge.com;

Adjusting Tag Loading Priority

The standard Extole implementation prioritizes having minimal impact to your customers' page load times. Extole does this by using various browser and JavaScript features to load asynchronously and progressively. If your goal is to reduce any page flicker that may occur from loading content from Extole, you can change the way the Extole tags are implemented.

Core tag

Typically customers will load the Extole core tag at end of the body element of a page like this:

<script type="text/javascript"
src="https://refer.brand.com/core.js" async></script>

This means the core tag will not load until after the full page HTML DOM has been rendered and Extole will load asynchronously while other scripts continue to load.

To increase the priority of loading the core Extole library the following steps can be taken:

Step 1
If you are using a tag manager, remove Extole from the tag manager and place it directly into your HTML.

Step 2
Remove the async keyword from the tag. This will block the page from loading until the core tag has been fetched and run.

Step 3
Make sure the script is loaded inside the head section of your HTML. When used in conjunction with removing the async keyword, this will prevent the page content (DOM) from loading until after the Extole script has been initialized.

Marketing tags

When an Extole Marketing Tag is loaded, it will reference an HTML element_id or element on the page. If the element is available it will immediately insert content into it. If the element is not yet available on the page the tag will poll the page to see if the element appears later.

Option 1

If your page uses HTML to display the element the tag will look like <span id="extole_zone_global_header"></span> and you should place the createZone tag in the HTML directly, immediately after the span tag, to cause the content to immediately load:

<span id="extole_zone_global_header"></span>
<script type="text/javascript">
(function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
extole.createZone({
  name: 'global_header',
  element_id: 'extole_zone_global_header'
  });
</script>

Option 2

If you dynamically load content onto the page through Angular, JQuery, or other tools, you'll want to place createZone in your JavaScript as soon as the element is created.

$( ".inner" ).append( "<p>Test</p>" );
var extoleHeader = $("<span>").attr('id','extole_zone_global_header);
$("#header_menu").append(extoleHeader);
(function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);

extole.createZone({
  name: 'global_header',
  element: extoleHeader
});

createZone Method

The center of tagging with Extole is the createZone method. The createZone method is used to make a content request to Extole or to track an event in Extole.

Extole includes Magic Script inside each tag. The purpose of the Magic Script is to allow tagging to work before the Extole core tag has been fully loaded. The Magic Script says: "If Extole Core is already loaded, then send messages to Extole. If it is not loaded yet, then store the request so it can fire when Extole is loaded."

The Extole Magic Script should be included with all Extole tags.

/* Start Extole */
(function(c,e,k,l,a){c[e]=c[e]||{};for(c[e].q=c[e].q||[];a<l.length;)k(l[a++],c[e])})(window,"extole",function(c,e){e[c]=e[c]||function(){e.q.push([c,arguments])}},["createZone"],0);
/* End Extole */

createZone Parameters

Zone FieldDescription
zoneSettings
required
Plain Object
A map of parameters passed into the zone creation.
createZoneDoneFunction(error,zone)
An optional callback function when the zone request is complete.

zoneSettings

Zone FieldDescription
name
required
String
The name of the zone that will be created and called. These are the names that appear in Extole's Campaign Editor.

Typically, tags include promotional CTA zones as well as registration and conversion zones.
elementElement
An HTML element where any content returned by the zone will be inserted. The element must already exist in the DOM to be able to pass it to Extole as an object. This typically makes sense for Single Page Apps or if you are doing direct development.

If the createZone tag does not include an element or element_id, the content will be appended to the end of the page. This is fine for overlays or tracking steps (registration/conversion).

Elements can be accessed using pure JavaScript or JQuery. For Example:
document.getElementById("extoleCTA")
$("#extoleCTA")
element_idString
The ID attribute's value of the element you want to get.

An element ID attribute that can be targeted on the page where any content returned by the zone will be inserted. Extole will scan the page DOM on an interval looking for the element with the provided ID attribute. When the element is found, Extole will call the zone and insert the content into the element.

If the createZone tag does not include an element or element_id the content will be appended to the end of the page. This is fine for overlays or tracking steps (registration/conversion).
dataPlain Object
An optional list of parameters that are passed into the zone to provide additional context about the person or the event (see table below).

zoneSettings.data

Zone FieldDescription
first_nameString
The first name of the person making the zone request. This is typically the advocate on a CTA zone or the friend on a registration or conversion zone.
last_nameString
The last name of the person making the zone request. This is typically the advocate on a CTA zone or the friend on a registration or conversion zone.
emailString
The email of the person making the zone request. This is typically the advocate on a CTA zone or the friend on a registration or conversion zone.
partner_user_idString
A unique user identifier that is provided at the time of registration and conversion.

If the user ID is provided at registration, it may be used at conversion for successful tracking of the referral.
partner_conversion_idString
A unique conversion identifier that is provided at the time of conversion.

If it is provided at conversion it may be used with approvals and fulfillments.
coupon_codeString
This is the coupon code. It is most commonly used on a registration or conversion tracking call. It will also be used as a method to tie the registration/conversion back to an advocate.
advocate_codeString
When using an Extole Advocate Code, you can pass the advocate code into any step for the friend (registration, conversion) to create the relationship between the advocate and the friend.
cart_valueString
Used on a conversion event to track the value of the purchase for revenue reporting.

createZoneDone(error, zone)

This is the JavaScript method that is called when the createZone tag completes. Its use is entirely optional.

Zone FieldDescription
errorA JavaScript Error object which may contain message, statusText, and status.
zoneThe newly created Zone object.

userService.logout()

Sometimes it may be required to trigger a logout of the user from the Extole system. A logout will cause Extole to delete the access token and cookies from all domains, and additionally call the Delete Token Consumer API which invalidates the token server-side at Extole.

This function requires that the Extole Core JS Library has been loaded on the page.

extole.require(['core-root:///common/user-service.js'], function (userService) {
    userService.logout();
});