Using Server-Side JavaScript in Optimizely Event Handlers
In December 2021, I threw together a proof of concept for delegating event handler logic in Optimizely Content Cloud to sandboxed JavaScript, executed server-side.
For this particular POC, I was able to change the URL setting logic from the Edit Mode UI and have that logic used without redeploying any file-based code. Traditionally, this is something that has required custom C#, deployed into the runtime.
I used Jint which is an open-source C# wrapper around ECMAScript.
I stored the JS on a start page property called UrlSegmentBuilder
. This could be edited from the UI (a better IDE would have been helpful).
This particular code set the URL segment of a new page to the current date (ex: 2022-01-05
).
The way I wrote it, you just needed to set the data.Segment
value in the JS. (But, see below, because there are a bunch of other ways to get the data in and out of Jint. I don’t know what the best way would be – this would require some testing and feedback.)
Here is the event handler code I used. Clearly, this would need to be generalized, include error handling, and use some execution constraints for safety.
urlSegmentCreator.Creating += (s,e) =>
{
// Get the raw JS code
var startPage = repo.Get<PageData>(ContentReference.StartPage) as StartPage;
if(!string.IsNullOrWhiteSpace(startPage.UrlSegmentBuilder))
{
// This is the object that will "carry" the data into and out of the JS
// (See note below. I should have been able to do this with a string.)
var data = new Data(){ Segment = e.RoutingSegment.RouteSegment };
var engine = new Engine()
.SetValue("data", data) // Push the data in...
.Execute(startPage.UrlSegmentBuilder); // ...execute the JS...
e.RoutingSegment.RouteSegment = data.Segment; // ...read the data out
}
};
(I should have been able to use a string
, but for some reason I couldn’t get that value to set and be readable outside the JS code. I had to create a simple object – the Data
class – and set the property. Not sure why.)
There are other ways to get data in and out:
- Call an
output
JS function, that maps to a C# method - Use the
Evaluate
method to directly return an assignable C# value - Call
GetValue
after execution, to read a JS variable into C#
The first time my POC was executed on start-up, it look 64ms, but I think most of this was for parsing, or maybe just some startup lag. On subsequent executions, it didn’t even register – it reported 0ms execution.
I measured it in ticks, and it was something like 64,000, which is about two-thirds of one millisecond.