Redirect and view tracking logic

FunnelFlux has three primary navigation-related actions that occur:

  • Entrance link loading: /fts/
  • Action link loading: /action/x
  • Page view tracking by JS: POST to /js/funnel

Entrance links are quite strict and contain all necessary data to route to a destination (since you would have generated them in our UI), and if they work, they will go exactly where specified, ignoring any other contextual history as an entrance link is a standalone, new entrance into a funnel.

In the latter two cases, the FunnelFlux Pro edge uses available information to determine what node/page a user is on and in the case of actions, what connection to travel down.

These can be prone to issues if not configured correctly, so this section will summarise how the JavaScript and action links determine current page, and originating page/node, respectively.

Action link logic

Action links will always execute the numbered action extending from the node they think the visitor is on.

When testing a funnel and navigating its useful to consider the funnel diagram and how each action results in you moving from one node to the next, keeping track of what node you are on (i.e. what the tracker knows you to be on).

Consider a situation where you go to a page > click an action link > it opens in a new tab. You go back to the original tab and click a link again. You are now initiating an action from a previous node that comes before the current known node position.

Consider a second scenario but where the action link does not open in a new tab. You then click the back-button on your browser, loading the previous page. If there is no view-tracking JS on this page, the tracker is unaware that you have navigated back to it. If you click an action link now, once again you are initiating an action from a previous node.

In both cases the tracker needs some mechanism of determining these repeat clicks, by determining the originating node of a click.

Handling of referrer

On loading an action link our edge will check referrer.

If this referrer contains a VID, the edge is now aware of the visitor session (without needing cookies).

If this referrer contains the full page URL, the tracker can now match that URL against known nodes/pages in the funnel, as well as previous visited pages, to determine the click came from a page that was already visited (a necessary event for a clickthrough to exist).

If the referrer contains a n=NODE_ID parameter in the URL, the tracker can now accurately determine originating node, without relying on page URL matching. This is more specific, as the same page might be used multiple times in the same funnel (with different node IDs), or a page might be embedded in an iFrame where the parent URL and thus referrer does not represent the loaded page.

This is why our JavaScript has two helper functions:

One that checks the <meta name="referrer"> tag on the page and if present, updates its value to no-referrer-when-downgrade, and if not present, creates it.

A second function that rewrites current page location to include visitor ID and current node ID in the URL, making the full referrer value highly informative to the action link handler.

Given this, one should avoid ever having rel="noreferrer" attributes added to links. This is a nonsensical thing to do -- hiding information from your own tracking system!

Nuance with pages hosted on a root domain

One interesting nuance can arise when full referrer is not passed.

Consider a funnel that has an initial landing page A at (i.e. the root domain/homepage), which connects to a second page B with URL

In the browser, the user will load page A and successfully navigate to page B.

On page B however, if full referrer is not passed, there next action click may pass a truncated referrer (hostname only). Our edge then sees a click apparently arising from "".

Uniquely, since the user has used their root domain as a page, this referrer is the known URL/path of the previous lander, so the tracker will rightfully determine, with the information given, that this is in fact a repeat click from page A.

This leads to a redirect loop of page A > click > page B > click > page B > click page B

Direct URL parameter injection

Another one of our JS helper functions will detect <a> elements on a page where href contains /action, then inject:


If this occurs, the referrer information is not used, as directly specified URL parameters take priority.

One could argue that the referrer and URL rewrite functions may be useful -- but this is not the case.

There are many situations where users can add JS code to a page, but don't use simple <a> elements to redirect to the next page. They may have <a> elements but that direct link to other pages, where they are unable to inject parameters into those URLs. The redirects to action URLs could also be managed by JavaScript, where the user has little input or dynamic control.

In any case, the "rn" parameter explicitly specifies to our edge that a click is coming from a specific node for the corresponding visitor. It's the most robust way to guarantee reliable tracking.

In advanced cases where redirection to action links does not involve simple <a> elements, but JavaScript manipulation, we'd recommend using the onDone() function in our view-tracking JS.

You can use this to obtain the current node ID and visitor ID then inject these into whatever functions control redirection > manually append the earlier URL parameters to the action URL, providing the same benefit.

Default action parameters

These can be toggled on when using the "get action link" context menu item in the funnel builder.

They are only available here as the must be specific to a funnel and node.

This toggle is just for the generation, it does not apply any specific effect to the funnel/node itself.

These URLs declare a default funnel and node ID, like so:


It's important to note that these values are NOT overrides, they will only be used for an action link request where no VID value is known, i.e. a new or unknown visitor.

Thus, they will work in an incognito window, whereas the generic/universal action links, without context, would not.

In 99% of cases these fallback parameters are not used -- but there are a few scenarios where they are useful, if not critical:

  1. When doing form submits that redirect through some third-party before returning to a redirect URL that is set in that third-party. Here, because of the random hops you don't control, if you used a generic action link it would likely load and have no useful referrer info (only info from the random third party system). The edge would only be able to use cookies to determine VID (not reliable!), so default params would be important to at least get the user to the expected destination, even if their session is lost and they are disconnected from their original funnel entrance. If the third-party could ingest and pass URL parameters forward, great! But, in many cases this isn't available...
  2. When sending users to some page where they need to clickthrough to an action link, but for whatever reason, its not possible to control page code to inject our JS that would help referrer/data passing
  3. When users may jump from a known, tracked page, to some other pages then come back to a known page -- e.g. through some Webinar flow, where you are likely to lose session tracking but still want to track some final action/clicks and ensure the visitors still redirect to an intended destination

In other words, these action links are helpful in all the irritating situations where you don't have control over making the tracking robust and can expect zero reliability of referrer/cookies/data passing, but still want people to load a link that you control at some later point.

JavaScript page view tracking logic

The page view tracking event via our JS only has two sources of data - the current URL (and its query string), and the embedded attributes.

The URL parameters always take priority. This way a page can embed JS with selected default IDs, but entrance links generated in our UI will always track as expected by overriding those values.

In the case of direct links, the query string URL params override the JS defaults.

In the case of redirect links, the resulting page is loaded without such params but an injected vid=VISITOR_ID value. 

This VID is passed in the JS POST request and so returns the already knowns node ID the user is navigating to, which then overrides the JS defaults.

Here are some other scenarios, and the resulting behaviour:

  • A redirect link loads the page, which has JS but with no embedded defaults. Here the VID will be present in the URL and be used, and the page's URL will be used to determine the current page. This will likely match the destination the redirect went to, resulting in no extra page view being generated (deduplication)
  • A page loads with no URL parameters and JS with no embedded parameters set. The view tracking will fail, as a funnel ID must always be passed -- it would only work if a VID was present to determine session, which would contain a current funnel ID.
  • A redirect link loads a page which has JS in it, containing embedded parameters that mismatch the current session/funnel. In this case the VID will be known and take priority, so funnel will not change. A view to the expected page has already been generated by the redirect, and the JS view event will automatically track with URL matching. If the JS specifies a page ID that mismatches the page the redirect served, it may cause a separate anomalous view if the declared page ID exists in the current funnel (else it would error)
  • No URL parameters present. Embedded parameters are used but with a page ID specified that does not exist in the current funnel. The view will fail to track.
  • No URL parameters present. Embedded parameters use a node ID that doesn't exist in the declared funnel ID. The view will fail to track.
  • No URL parameters present. A page ID is present, but the current URL does not match that page ID. The edge will honour the page ID, ignoring URL matching. This allows iframing/embedding to function as expected.

Was this article helpful?