Solution 1:

The safest way is to pass the needed data to the HTML directly. If you use properties or cache service it can get complex or fail under multiple simultaneous users.
There are many techniques to pass an initial object from the server (.gs) to the client (.html).

Using HtmlTemplate, you may do:
//.gs file

function doGet() {
    var htmlTemplate = HtmlService.createTemplateFromFile('template-client');
    htmlTemplate.dataFromServerTemplate = { first: "hello", last: "world" };
    var htmlOutput = htmlTemplate.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME)
        .setTitle('sample');
    return htmlOutput;
}

and in your template-client.html file:

<!DOCTYPE html>

<script>
    var data = <?!= JSON.stringify(dataFromServerTemplate) ?>; //Stores the data directly in the javascript code
    // sample usage
    function initialize() {
        document.getElementById("myTitle").innerText = data.first + " - " + data.last;
        //or use jquery:  $("#myTitle").text(data.first + " - " + data.last);
    }
    // use onload or use jquery to call your initialization after the document loads
    window.onload = initialize;
</script>


<html>
<body>
    <H2 id="myTitle"></H2>
</body>
</html>

It is also possible to do it without using templating, by appending a hidden div to an HtmlOutput:

//.gs file:

function appendDataToHtmlOutput(data, htmlOutput, idData) {
    if (!idData)
        idData = "mydata_htmlservice";

    // data is encoded after stringifying to guarantee a safe string that will never conflict with the html.
    // downside: increases the storage size by about 30%. If that is a concern (when passing huge objects) you may use base94
    // or even base128 encoding but that requires more code and can have issues, see http://stackoverflow.com/questions/6008047/why-dont-people-use-base128
    var strAppend = "<div id='" + idData + "' style='display:none;'>" + Utilities.base64Encode(JSON.stringify(data)) + "</div>";
    return htmlOutput.append(strAppend);
}


// sample usage:
function doGet() {
    var htmlOutput = HtmlService.createHtmlOutputFromFile('html-sample')
        .setSandboxMode(HtmlService.SandboxMode.IFRAME)
        .setTitle('sample');

    // data can be any (serializable) javascript object.
    // if your data is a native value (like a single number) pass an object like {num:myNumber}
    var data = { first: "hello", last: "world" };
    // appendDataToHtmlOutput modifies the html and returns the same htmlOutput object
    return appendDataToHtmlOutput(data, htmlOutput);
}

and in your output-client.html:

<!DOCTYPE html>
<script>
    /**
    * getDataFromHtml
    *
    * Inputs
    * idData: optional. id for the data element. defaults to "mydata_htmlservice"
    *
    * Returns
    * The stored data object
    */
    function getDataFromHtml(idData) {
        if (!idData)
            idData = "mydata_htmlservice";
        var dataEncoded = document.getElementById(idData).innerHTML;
        var data = JSON.parse(atob(dataEncoded));
        return data;
    }
    // sample usage of getDataFromHtml
    function initialize() {
        var data = getDataFromHtml();
        document.getElementById("myTitle").innerText = data.first + " - " + data.last;
        //or use jquery:  $("#myTitle").text(data.first + " - " + data.last);
    }
    // use onload or use jquery to call your initialization after the document loads
    window.onload = initialize;
</script>
<html>
<body>
    <H2 id="myTitle"></H2>
</body>
</html>


Both methods are compared and better explained in this little github I made: https://github.com/zmandel/htmlService-get-set-data

Solution 2:

I often use HtmlService templates to push static values to the client.

index.html

<script>
 var domain = "<?=domain?>"; 
</script>

code.gs

var ui  = HtmlService.createTemplateFromFile('Sidebar');
ui.domain = domain;
return ui.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle(strings[lang][domain]);

Solution 3:

In your code:

function scriptUser_(userId) {
  if (userId !== undefined)
    sUserId = userId; // Global variable
  try { return sUserId; } catch (e) { return undefined; }
}

You are assigning a value to the global variable named sUserId. But, then when you try to retrieve it, nothing is there. Global variables loose their value as soon as the current instance of the code bring run is completed. Global variable don't persist their values.

You'll need to use the Properties Service to store the value. Or you could use the Cache service. If you want the value of the user id to expire after some time, use cache service.