How to return a constant variable from custom js?

We are trying to capture click url in a custom js variable. The following returns undefined. Would anyone be able to help us out and kindly point out our error please :slight_smile:

function() {

    if ({{Click Url}}) {

        return {{Click Url}}.split(':')[1];

    }

}

If we return a constant, say “a”, the function returns a. If we return {{Click Url}} without the if clause we still get undefined.

Have we missed some point in your documentation?

Thank you!

Hi @panukuulu, thanks for reaching out! There are two things to be considered here:

  • At the moment we don’t support using Tag Manager variables inside the Tag Manager variables, that’s why the setup above doesn’t work.

  • The built-in Tag Manager variable you’ve used above has all the characteristics of a custom variable (it can be used both as a trigger condition and as a variable in a tag).

Please let me know if using the split() method to get rid of the protocol (http: or https:) is the only reason you’ve decided to go for a custom js variable or is there anything else you would like to achieve? Once that’s clarified - we will be able to recommend the most convenient solution.

Thank you! :slight_smile:

Hi,

Thank you for your response. Yes, split is the only reason.

The solution we found is creating a tag that picks up the click url, formats that and passes it to the data layer. We can then read the formatted value to a data layer variable and use that.

Is this a sensible solution?

Ok, thanks for clarifying this one for me. In this case - I’d go with a Custom JS variable. Please use the following code:

function() {
    document.addEventListener('click', function(e) {
    e = e || window.event;
    var target = e.target || e.srcElement,
        url = target.href.replace(/^https?\:\/\//i, "");
      window.clickUrlTrimed = url;
}, false);
  return window.clickUrlTrimed;
}

Please test it and let me know if that’s what you was looking for :slight_smile:

Thanks!

Hi Piotr,

I am trying to configure a Goal conversion tag for PDF file downloads, and I used your code as a starting point to capture the file name.

Here is my Custom JS variable that retrieves the file name from the click url :

function() {
    var decodedFilename;

    document.addEventListener('click', function(e) {
        e = e || window.event;
        var target = e.target || e.srcElement;
        if (target && target.href && target.href.includes('.pdf')) {
            var filepath = target.href.split('/');
            var filename = filepath.pop();
            decodedFilename = decodeURI(filename);
        }
    }, false);

    return decodedFilename;
}

When I console.log(decodedFilename) I see that this code is working as expected, but my issue is that when I use this variable in a custom dimension the value that gets sent with the Goal conversion is always empty.

I am using a Click trigger with the following settings:

  • Wait for tags before loading the next page : ON
  • Fire when Click Url contains .pdf

My guess is that the Goal conversion tag is being sent before the JS code has time to return its value. Is there any way to add a slight delay to the Goal conversion tag using the standard Click trigger? :thinking:

If this is not possible, do you have any recommendations for this specific scenario?

Thank you!

Hi @joao,

There has been a few changes since that answer in our product and now you can use variables inside of variables. This means that you can use the {{ Click Url }} in order to get the clicked elements url and there is no need for the event listener.

Just as a tip, you can wrap your code in try / catch to prevent any errors when the value is not available since every variable in Piwik PRO is refreshed on every event. This also means events such as scroll where the click url won’t be available causing errors.

function() {

try {
var clickUrl = {{ Click Url }};
// your code

}
catch (e) {
 return undefined;
}

}
2 Likes

Hi Kamil,

Thank you for your reply, this is good to know.

I have now simplified my code to use the {{ Click Url }} variable:

function() {
 var clickUrl = {{ Click Url }};
 if (clickUrl && clickUrl.includes('.pdf')) {
   var filepath = clickUrl.split('/');
   var filename = filepath.pop();
   return decodeURI(filename);
 }
 return undefined;
}

(I personally prefer to check if the click url exists in the if condition instead of using try catch.)

As an added bonus, this seems to solve the sync issue I was having and the filename is now being correctly sent as a custom dimension, thank you! :heart_eyes:


The fact that custom JS variables are evaluated once for each event, that doesn’t seem very efficient: this means the code will potentially run hundreds of times for each session. Can this not become a performance issue as you start creating a few of these variables?

Is this how other tag managers work as well (e.g. GTM’s Custom JS variables)?

Hi @joao,

No worries, when it comes to the question about variables it seems that it was already answered in another thread - Custom JS variable evaluated multiple times per page - #6 by mbaersch

Have a great day! :slight_smile: