Simple Way to Extract GET Params from a JavaScript Script Tag

Here’s a simple trick to extracting HTTP GET style parameters from a <script> tag, from within the script itself.

Motivation

At Heyzap, we create a variety of games widgets that publishers can embed on their sites to instantly get great game content. Publishers can choose which games appear on their widget by supplying a custom “embed key” to the widget.

Oh, by the way… Heyzap is hiring great engineers like you!

Typically, you’d supply extra context to a javascript embed as follows:

<script type="javascript" src="http://www.blah.com/myscript.js"></script>
<script type="javascript">
new HeyzapWidget({key: "123"});
</script>

It would be much nicer, however, to be able to do this in one line:

<script type="javascript" src="http://www.blah.com/myscript.js?key=123"></script>

This way we’d be able give publishers only one line to copy and paste into their site, rather than four.

You could provide this “one line” version to publisher if the javascript was dynamically served, eg. if a rails/django/php page examined the GET params, and injected them into the script body. This is not very practical under heavy loads and it would be nicer and much more flexible to serve a static javascript file.

Ideally we want to be able to do this entirely in javascript in the file we are including. This way, we can host the file anywhere, including cloud services such as S3.

Shut up and show me some code…

// How to use
var options = getParams("scriptname.js");
 
// Extract "GET" parameters from a JS include querystring
function getParams(script_name) {
  // Find all script tags
  var scripts = document.getElementsByTagName("script");
 
  // Look through them trying to find ourselves
  for(var i=0; i<scripts.length; i++) {
    if(scripts[i].src.indexOf("/" + script_name) > -1) {
      // Get an array of key=value strings of params
      var pa = scripts[i].src.split("?").pop().split("&");
 
      // Split each key=value into array, the construct js object
      var p = {};
      for(var j=0; j<pa.length; j++) {
        var kv = pa[j].split("=");
        p[unescape(kv[0])] = unescape(kv[1]);
      }
      return p;
    }
  }
 
  // No scripts match
  return {};
}
 
// Mini version :)
function getParams(a){var b=document.getElementsByTagName("script");
  for(var i=0;i<b.length;i++){if(b[i].src.indexOf("/"+a)>-1){
    var c=b[i].src.split("?").pop().split("&"); var p={};
    for(var j=0;j<c.length;j++){var d=c[j].split("=");p[d[0]]=d[1]}return p}
  }
  return {}
}
  • athikitie
    Hemp is is far more than a psychoactive drug. And indeed the perfect food, and when learned. Go to http://www.hempproteinguide.net/ for great information.
  • Amardeep S Kohli
    <script type="text/javascript">dcsMultiTrack('DCS.dcsuri','/a/b/c/d/e','DCS.dcsqry','_ABC=ABC_0001','DCSext.error_code','abc500','DCSext.error_desc','FAILURE','DCSext.error_type','ABC Error','DCSext.RegType','ABC Registration','DCSext.RegStep','ABC Entry');</script>


    Suppose, there is a script with dcsMultiTrack method with its comma seperated values within the tag HTML page (as shown above).

    Is it possible to fetch each of these comma seperated using JavaScript function at page load and stor them into sifferent variables? Can someone please help me out and share the code snippet for the same.

    Thanks in Advance!

  • harry
    This post does not deserve to be hacker news. Extracting params in js can be done in easier ways.

    Also including a new file increasing loading time of the page. The function should be written in the same file.
  • Hey harry. This is not intended to be included in a new file, it should be in the same file thats being included (otherwise it wouldnt even work!).

    Have you got some examples of easier ways to extract params from an included js file?
  • The one problem is that this breaks caching across different sets of params. If all you want is to have one html tag that includes settings then you could use html params instead of get params:

    <script data-settings="key=123" src="http://www.blah.com/myscript.js" type="javascript"></script>
  • script.aculo.us has been using this for loading optional components. Their solution is fairly similar, but worth taking a look at.
  • Chris Zacharias
    If you are cool with collecting your parameter values at parse time, you should be able to just do something like:

    var scripts = document.getElementsByTagName("script");
    var thisScript = scripts[scripts.length - 1];

    This works since the script is blocking, therefore the currently executing script is always the last one in the nodeset. However, you can break this if you are doing dynamic script loading after page load where the script nodes are inserted into the middle of the document and not at the end.
  • To follow up to what Chris Z brought up, I think you're better off starting your search from the end since the chance that the last script tag is the one you want is high. Something like:

    for (var i=scripts.length-1; i > -1; --i) { ...

    As a (maybe negligible) bonus, you're not checking scripts.length on every run through that loop either this way.
  • Great solution James. We should use that more in Heyzap :)
blog comments powered by Disqus