I followed this community post on how to programmatically trigger goals, and it works as advertised:

Sitecore.Data.Items.Item goalItem = Sitecore.Context.Database.GetItem(goalId);
var goalTrigger = Tracker.MarketingDefinitions.Goals[goalItem.ID];
var goalEventData = Tracker.Current.CurrentPage.RegisterGoal(goalTrigger);
goalEventData.Data = goalItem["Name"];
goalEventData.ItemId = goalItem.ID.ToGuid();
goalEventData.DataKey = goalItem.Paths.Path;
goalEventData.Text = "Goal for Logic";

However, seeing as this is put into an API and called from JavaScript, the API URL appears in Path Analyzer. A bit of googling reveals that you can do the following to prevent a page from showing up in Path Analyzer:


This single line of code seems to break the goal triggering. When the code is present, the triggering code is run, and the goal apparently triggered, but the goal never shows up in Experience Profile. If I remove that line, the goal shows up as expected in Experience Profile again.

We have previously used the Cancel() method with great success, but after the switch to Sitecore 9.x it stopped the goal from being registered properly.

I suspected it might have something to do with session timeouts and set <sessionState timeout="2"> in Web.config. I then waited for about 30 minutes, yet still nothing appeared in Experience Profile.

So the question is then: How can we programmatically trigger goals and have the API URL not show up in Path Analyzer?

Sitecore 9.1.0 (rev. 001564)

  • If you cancel the page, the goal will not be tracked. I would expect it to be consistent for both 8.x and 9.x. Have you considered using xConnect to save goals?
    – grg
    Dec 19, 2018 at 13:03
  • Checkout my answer here sitecore.stackexchange.com/questions/14966/… I have this working in 9.1 right now.
    – Chris Auer
    Dec 19, 2018 at 15:07

1 Answer 1


You need to do two things to make the goal show up and the API not be in the tracker. As you said in your question, you need to cancel the current call. I do this with a little cotroller atribute I borrowed from Habitat.

namespace Sitecore.Foundation.SitecoreExtensions.Attributes
    using System.Web.Mvc;
    using Sitecore.Analytics;

    public class SkipAnalyticsTrackingApiAttribute : ActionFilterAttribute
        public override void OnActionExecuting(ActionExecutingContext filterContext)

Then you API controller looks like this

public ActionResult TriggerGoal(string goalId)
    var response = new BaseResponseDTO<bool>();
    response.Data = registrationTrackingRepository.TriggerGoal(goalId);

    return new JsonNet(response);

The 2nd thing you need to do is to put the goal on the previous page. If you put it on the current page, the api call, it brings the page back into scope. Thus ignoring the Cancel() you did earlier.

I get the previous page with this bit of code. fromApi is a bool that tells my function whether this is from an API call or a server side call. For fromApi = true, I use the previous page.

    var goalDefinition = this.goalDefinitionManager.Get(goalId.Guid, CultureInfo.InvariantCulture);
    if (goalDefinition == null)
        Log.Warn($"Cannot find goal: {goalId}", this);

    Log.Info($"Goal Triggered: Contact: {Tracker.Current.Contact.ContactId} : {goalId}", this);

    var page = fromApi ? GetPageForApi() : Tracker.Current.CurrentPage;


private IPageContext GetPageForApi()
    if (Tracker.Current.Session.Interaction.PreviousPage == null)
        return Tracker.Current.CurrentPage;

    return Tracker.Current.Session.Interaction.PreviousPage;
  • I guess my error was that I was indeed registering the goal on CurrentPage instead of PreviousPage, and the goal was cancelled when I called Cancel() on CurrentPage. I changed this around a bit, and now my goal was triggered and the path analyzer does not show the API. Thanks for the pointers! :) Dec 20, 2018 at 10:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.