🎼 Now this is a story all about how
My code got triggered only once
And I’d like to take a minute - just sit right there
I’ll tell you how I spent my day registering to events 🎼
So far in our SFCC journey, we saw how to write code that gets triggered by an action (for example, browsing to a route); but what if we want to run code that corresponds to an event? SFRA allows us to hook to all kind of events, such as payment events or analytics events, but on this post, we are going to focus on two very special events: onSession
and onRequest.
Two Events Walk Into a Bar…
SFRA allows us to hook into all kinds of events, for example, app.communication.order.confirmation
that notifies on an order confirmation or app.template.htmlHead
, which, in turn, allows you to add content to the HTML head
element — each handles a specific event in the flow of the storefront life.
onSession
and onRequest
represents different type of events as they enable us to hook into the life cycle of a storefront request and receive notifications on two different states:
onSession
is called at the beginning of a new storefront session.onRequest
is called every single time a storefront request is received from the client.
Hook Me Up!
Hooking to events is done via a special file called hooks.json
. This file contains hook entries for any number of events we wish to hook to and has to be declared inside of the cartridge’s package.json
file. Each hook entry must contain the following two properties:
- Name: The extension point (hook name)
- Script: The script file to call when the event is fired.
🐘 Make sure that the script file you set for the hook entry contains a function which will run once the event is fired
For today’s project, we are going to hook to theonRequest
event, check every storefront request for a query param called magic
, and if found, and its value is true
, redirect the user to our Magic-Show
route.
We begin by declaring a hook entry for onRequest
:
- cd to the services folder of MagicCartridge (
cd cartridges/magicCartridge/cartridge/services
), and create a new file namedhooks.json
. - Add the following content to the newly created
hooks.json
:
{
"hooks": [
{
"name": "dw.system.request.onRequest",
"script": "./MagicValidator"
}
]
}
Let’s break this JSON down:
Line 2: Declares a key called hooks
and its value as an array of hook
entries.
Lines 3–6: A hook entry.
Line 4: Sets the name of the event we wish to hook to. In our case we wish to validate every request to our storefront, so we will hook to the onRequest
event.
Line 5: Sets the path and name of the script that will be called once the event fires. We will create the MagicValidator.js
file in the same folder as hooks.json
hence the use of ./
to specify the file path.
With the new hooks.js
file in place, it’s time to register it:
- cd to the root folder of MagicCartridge (
cd cartridges/magicCartridge
), and create a new file namedpackage.json
. - Add the following content to the newly created file:
{
"hooks": "./cartridge/services/hooks.json"
}
Answer the Call!
With hooks.json
registered, SFCC will fire an event for every incoming storefront request and call MagicValidator.js
each time to handle the event. In turn, MagicValidator.js
needs to export a method called onRequest
to handle the event.
Let’s add MagicValidator.js
to our cartridge and handle the event:
- cd to the services folder of MagicCartridge (
cd cartridges/magicCartridge/cartridge/services
), and create a new file namedMagicValidator.js
. - Add the following content to the newly created
MagicValidator.js
file:
var Status = require('dw/system/Status');
var URLUtils = require('dw/web/URLUtils');
function onRequest() {
if (request.httpRequest && !request.includeRequest) {
if (request.httpQueryString.match(/magic=true/ig)) {
response.redirect(URLUtils.url('Magic-Show'));
}
}
return new Status(Status.OK);
}
module.exports = {
onRequest: onRequest
};
So let’s see what we have here:
Line 5: Verifies the request we are processing is both an HTTP request and a top-level one (we don't want to start validating requests from remote sources on the page).
Line 6: Checks the request’s query params string for a parameter named magic
with the value of true
.
🐘 This query param check is rather naive and is only used in this case to demonstate the onRequest handler. If you are working with query params in your code — please use something better.
Line 7: Redirects the response to the Magic-Show
route using the URLUtils
class.
Line 11: If the request does not meet all of the above conditions, then pass the request back to SFCC’s request flow by setting its status to OK.
Lines 14–16: Exports the onRequest
method.
Go Wild 🌈
Armed with the new event handler let’s test our new feature! Browse to any RL in your site front (for example /home
). You should notice nothing changes and you are right on the home page as you should be. Now try to add the magic
query params (/home?magic=true
) and watch what happens:
No matter where we browse in our storefront now, we can go straight to the Magic route just by using a query param.
🐘 What if we want to be able to do this trick only once per session? Which event should we listen to in our hooks.json? (hint: it rhymes with passion)
And there you have it — a way to invoke code based on events and not by user interaction. Just make sure to use this wisely otherwise you will create some heavy load on the request flow, resulting in slow responses from the server.
Tomorrow we are going to deal with a really fun concept of SFCC — Jobs.
As always, looking forward to your comments either here or on Twitter 😎