Logging previous page and next page (if visited) to console

Twine Version: Sugarcube 2.36.1

I am building an xAPI-enabled Twine game that uses the Sugarcube 2 format. I would like to capitalize on Sugarcube’s built-in functionality to map useful events to my database. I would like to use the Story History API (or anything really!) to send xAPI statements that map the user’s current page (I can do this), what page they go to when they hit the back button, and what page they go to when they hit the forward button (these last two are far more tricky).

For example, “Doug clicked the Forward button from the Start page to go to the Blabla Passage.”

Right now my closest solution can generate something like “Doug clicked the forward button from the start page” but I would prefer to map the destination page as well.

I know Story History API has 3 main functions: Hasvisited() which returns true or false whether they’ve visited a page, Visited() which tracks the number of times a user has visited the page, and passage() which returns the name of the passage. I thought I could use these, but I think I was wrong.

When I develop JS functions the first step I like to take is getting the data correctly loaded, so I am not looking for a complete solution here. All I want to do right now is log the data in the console.

Anyone got a clue here? I would like a dynamic solution that doesn’t involve any hand-coding on my Passages (at most, a generic function I can add to all passages within their context).

If it matters, I’m compiling using tweego not the GUI.

As always, thank you.

— Doug

Looks like you could use State.peek(1) to get the
previous moment. Although it might be History.peek or something if you’re actually using version 2.3.0 from 7 years ago? I don’t remember the details of how it worked that far back. Looking at the documentation (and a quick peek at the source) the API doesn’t appear to have any way to get future moments. You could maybe check if State.length decreases to detect the back button? Not sure how you’d detect the forward button. Maybe you can add another event listener to the buttons that records when you click them? And then clear it when you read the data and send it.

That’s my thoughts of where I’d start experimenting, anyway. I assume you’re doing the data logging in a :passageend event or something like that? Hrm. That didn’t exist in 2.3.0. The PassageDone passage?

1 Like

if you’re actually using version 2.3.0 from 7 years ago?

Oh my gosh 2.0.0 is that old!? I just updated to 2.36.1 and recompiled; all is well.

Now that I’m current (hopefully… looks like the most recent changes on the repo were 2 years ago), I will dig in again.

Appreciate your help; if you have any pointers on the current ver let me know. It may indeed be looking forward is going to be difficult.

— Doug

Yeah, it’s been stable for a while, I think. I dug through the changelog briefly and it looks like not that much has changed, except the addition of all the navigation events if you want to get notified in JS rather than making special passages.

My biggest question is where you’re putting the logging code? Because if you log it only after a transition you might be able to look at only the current and previous moments and then find some other way to tell what triggered the transition? Hmm, or maybe at the beginning of a transition? :passageinit gets passed the incoming passage. So you could look at the current moment and the incoming passage? That would give you “Doug is going from (current passage) to (incoming passage).”

And then maybe you can use JS to tack extra event handlers onto the back and forward buttons to record whether it was a normal link click or a back/forward button click? Or zero out the default UI bar with… I think it’s UI.destroy()? and make your own back and forward buttons with the appropriate API functions?



This put me on the right track. I finally got both of these logging in the console thanks to your help. I am indeed tying them to the button IDs with an eventlistener.

Here’s the code that logs to the console, which is in my universal js. It is successfully rendering the code:

var currentPassage = null;
var incomingPassage = null;

$(document).on(':passagedisplay', function(ev) {
  if (currentPassage !== null) {
    console.log('Current passage:', currentPassage.title);
  incomingPassage = ev.passage;
  console.log('Incoming passage:', incomingPassage.title);
  currentPassage = incomingPassage;

Renders in console as:

Current passage: – "Start"
Incoming passage: – "disclaimer"
Current passage: – "disclaimer"
Incoming passage: – "survey question 1"

Thanks for helping me out here. I felt like I was beating my head on the wall, but updating + then revisiting the docs was the way to go!




You didn’t state if you’re intending to identify the end-user whose data you are tracking, although the 1st example in your original post…

Doug clicked the Forward button from the Start page to go to the Blabla Passage.”

…implies that you might be, and that could be considered the collection of Personal Information in some legal regions.

And even if you aren’t, the fact that the server will be receiving messages that potentially contains the end-user’s IP Address could be considered the potential collection of Personal Information in some legal regions.

So you might want to consider including/displaying a Privacy Policy some time prior to the collection of the end-user’s data, if you haven’t already done so.

1 Like

Yup, we are anonymizing Actors and including all that in a privacy statement. Thank you!