Passing data from <head> to a page

Question:

Is there a way to import Wix storage into the settings advanced code head tag?

Or can I access the default storage from a Wix page?

Or maybe there is another way I can pass data from head to a wix page?

Product:

Wix Studio Editor

What are you trying to achieve:

I set up branch.io inside the advanced code head tag to obtain link data when website is opened from a deep link. It works and I can log the link data however I am now unable to pass the data to a wix page.

I am trying to either use Wix storage in the head tag or access the default localStorage from a wix page but I’m open to any way to pass the data

What have you already tried:

Here is a very simple example to store data from the head

I am adding the code in the ‘Settings’ → 'Advanced → ‘Custom Code’ → ‘Head’

Inside the head:

<script>
    import {local} from 'wix-storage-frontend';
    local.setItem('testData', 'Rob');
</script>

Doesn’t work - looks like it can’t connect to wix storage from the head

However the default storage does work:
Inside the head:

<script>
    localStorage.setItem('testData', 'Rob');
</script>

However it is now stored separately from the wix storage data which I can’t find a way to access from a wix page:

How can I get the data from the head to a wix page?

Thank you for help!
Rob

Wix uses a virtual DOM so the code injected into <head> isn’t going to be able to interact with page code.

I’m not familiar with branch.io. Does it offer an npm package? As long as it’s not using DOM-specific functionality (ie. window/document) using an npm package directly from the page code could be a solution to the problem.

If not another option is to use a custom element to run arbitrary code and pass messages back and forth between your page and the element: Wix Editor: Adding a Custom Element to Your Site | Help Center | Wix.com

1 Like

Thank you very much for the information!

I went with the NPM package initially but unfortunately it does use DOM-specific functionality and will not initialize

‘ReferenceError: window is not defined’

I have been trying to access the default localStorage from an iFrame html with no success. It is my understanding that as long as the src is the same domain as my site they should share a localStorage but it has not been my experience.

I did manage to get the linkData to a page but I am not sure how reliable of a solution it is and would very much appreciate your input.

Here is the full script inside the head tag:

<script>
    (function(b,r,a,n,c,h,_,s,d,k){if(!b[n]||!b[n]._q){for(;s<_.length;)c(h,_[s++]);d=r.createElement(a);d.async=1;d.src="https://cdn.branch.io/branch-latest.min.js";k=r.getElementsByTagName(a)[0];k.parentNode.insertBefore(d,k);b[n]=h}})(window,document,"script","branch",function(b,r){b[r]=function(){b._q.push([r,arguments])}},{_q:[],_v:1},"addListener banner closeBanner closeJourney data deepview deepviewCta first init link logout removeListener setBranchViewData setIdentity track trackCommerceEvent logEvent disableTracking getBrowserFingerprintId crossPlatformIds lastAttributedTouchData setAPIResponseCallback qrCode setRequestMetaData setAPIUrl getAPIUrl setDMAParamsForEEA".split(" "), 0);
    // init Branch
    branch.init('my_key_live', function(err, linkData) {
        if (err != null) {
            console.log(err.message);
        } else {
            const data = linkData.data;
            const json = JSON.parse(data);
            const dataString = json['$deeplink_path'];
            console.log('deep link: ' + dataString);
            var wixStorage = JSON.parse(localStorage.getItem('platform_app_675bbcef-...'));
            wixStorage.linkData = dataString;
            var jsonString = JSON.stringify(wixStorage);
            localStorage.setItem('platform_app_675bbcef-...', jsonString);
        }
    });
</script>

The code in question would be:

var wixStorage = JSON.parse(localStorage.getItem('platform_app_675bbcef-...'));
wixStorage.linkData = dataString;
var jsonString = JSON.stringify(wixStorage);
localStorage.setItem('platform_app_675bbcef-1...', jsonString);

This is the result:

It appears to work i can then access it on a wix page through

import {local} from 'wix-storage-frontend';

I can continue to freely add and remove other key values from the wix storage and it remains unaffected. I can also remove that key value - ‘linkData’.

However I notice it only works on the published site and returns null in the test environment but for the most part it seems to work.

Questions:
Is the ‘platform_app_id’ in local storage a static unique value?
Across all browsers and sessions?
Does it ever change?
And I suppose it’s not sensitive considering I was able to find it in my live storage?

In the meantime I will explore the documentation that you have provided regarding the ‘Custom Elements’ to see if I can come up with another solution down that route. I really appreciate your input and the information provided.

Thank you,
Rob

Amazing! With custom elements I can do either:

  1. Initialize branch.io from the npm module and grab the link data there

or

  1. Access the site default localStorage and grab the link data from there

Thank you so much!

I do have one more question though if you don’t mind. Here is the code in my custom element:

import branch from 'branch-sdk'

class BranchIO extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {

    var branchResult = '';
    branch.init('key_live_p...', function(err, data) {
      if (err != null) {
        branchResult = err.message;
      } else {
        branchResult = JSON.stringify(data);
      }
    });

    this.addEventListener('click', () => {
      this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
    });
  }
}
customElements.define('branch-io', BranchIO);

Question:

How do I ‘addEventListener’ to automatically trigger after Branch has finished initializing?

As of now it can only trigger it when it is clicked

I’ll leave this here for anybody else trying to initialize Branch-sdk in a wix project:

Add a custom element
Make sure to set the ‘Tag name’ of custom element in this case I named it ‘branch-io’
Same name as the ‘branch-io.js’ file
And add the ‘branch-sdk’ npm

Custom Element Code:

import branch from 'branch-sdk'

function initializeBranch() {
  return new Promise((resolve, reject) => {
    branch.init('key_live_...', function(err, data) {
      resolve(JSON.stringify(data));
    });
  });
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

class BranchIO extends HTMLElement {

  constructor() {
    super();
  }

  async connectedCallback() {
    const branchResult = await initializeBranch();
    await delay(1000);
    this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
  }
}

customElements.define('branch-io', BranchIO);

Page code:

$w.onReady(async function () {
    // branchElement is the wix id of the custom element
    $w('#branchElement').on('clickedCanvas', (event) => {
        console.log('link data received ' + event.detail);
        // Do what you need with the linkData
    })
});

I’ve tried a lot of possible scenarios. The delay is the only way I can get it to reliably fire when opened in live mode from an actual link.

Happy coding,
Rob

The code is synchronous so there’s no need need to have an addEventListener at the end of the connectedCallback and generate a click() event in code. Can just this.dispatchEvent(new CustomEvent('myEvent'... at the end of this function and it’ll dispatch the event.

connectedCallback is called whenever an HTMLElement is added to a page. Can read more about the lifecycle here: Using custom elements - Web APIs | MDN

Can you clarify this?

If for some reason addEventListener is needed can try other events, for example: Document: DOMContentLoaded event - Web APIs | MDN
/ Event reference | MDN

1 Like

Thanks for the info it helped me come up with an even better solution!

Heres what I mean about the block (when this.dispatchEvent is called inside a inside another function / thread)

This will log the correct data but won’t fire to the page:

connectedCallback() {
  branch.init('key_live_...', function(err, data) {
    if (data != null) {
      const branchResult = JSON.stringify(data);
      console.log(branchResult);
      this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: '' + branchResult}));
    }
  });
}

This will also log but won’t fire to the page:

connectedCallback() {
  const delayInMilliseconds = 1000;
  setTimeout(function() {
    console.log('1 second passed fire event');
    this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
  }, delayInMilliseconds);
}

I suspect that the reference to ‘this.’ is changing inside the block/thread and I can confirm it with this:

connectedCallback() {
  console.log(this); // logs: <branch-io></branch-io>
  const delayInMilliseconds = 1000;
  setTimeout(function() {
    console.log(this); // logs: Window {}
    this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
  }, delayInMilliseconds);
}

However I learned I can set up a promise function outside the class and the async / await syntax works (this will fire every time):

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
async connectedCallback() {
  await delay(1000);
  console.log('Second passed fire');
  this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: 'test data'}));
}

Now very strangely if I do the same for the ‘branch.init’ function it will fire in test mode, and the first live load, but not when opened from an actual link. It will log the correct data though:

function initializeBranch() {
  return new Promise((resolve, reject) => {
    branch.init('key_live_...', function(err, data) {
      resolve(JSON.stringify(data));
    });
  });
}
async connectedCallback() {
  const branchResult = await initializeBranch();
  console.log('Result ' + branchResult);
  this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
}

I suspect here that maybe the ‘dispatchEvent’ is attempting to fire before the main page has finished loading and the ‘.on’ is connected so with that and the new information you gave me led to this solution:

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
function initializeBranch() {
  return new Promise((resolve, reject) => {
    branch.init('key_live_...', function(err, data) {
      resolve(JSON.stringify(data));
    });
  });
}
// Then inside the class 
class BranchIO extends HTMLElement {
  constructor() {
    super();
  }
  async connectedCallback() {
    const branchResult = await initializeBranch();
    await delay(1000);
    this.dispatchEvent(new CustomEvent('clickedCanvas', {detail: branchResult}));
  }
}

That will fire every time both test, live and real link opens and I think it definitely ensures that the branch init will be finished by the time the call is made. I’m very happy with that solution :smiley:

Thank you!