If you try to do the search and make sure that you are using it as a non logged in user and click on the page in the result, do you see the page?
It might be so that the result is pages that can't be accessed by ordinary users
@Henrik Fransas: Thank you for your reply, I actually went over your articles to implement this.
Another thing is that I am creating the blog article pages dynamically from an xml file. I have created a custom page for it, and also has a corresponding viewmodel for the page. Below is the sample of my code when I use search:
Code to track the query and populate HitId and HitType properties
var searchResults = client.Search<ArticlePage>().For(q).Select(x => new ArticleListTrackViewModel
{
ArticleCategory = x.ArticleCategory,
Created = x.Created,
PageTitle = x.PageTitle,
ArticleLink = x.ExternalURL,
Author = ArticleHelper.GetAuthorName(x.Author),
HitType = "ArticlePage" (I am hard coding this)
}).GetResult();
var hits = searchResults.Hits;
foreach( var obj in hits)
{
obj.Document.HitId = ArticleHelper.GetPageID(obj.Document.PageTitle); (The helper gets the PageGuid)
}
model.TrackId = new TrackContext().Id;
SearchClient.Instance.Statistics().TrackQuery(q, x =>
{
x.Id = model.TrackId;
x.Tags = ServiceLocator.Current.GetInstance<IStatisticTagsHelper>().GetTags(false);
x.Query.Hits = searchResults.TotalMatching;
});
model.NumberOfHits = searchResults.Hits.Count();
model.Results = searchResults;
return View(model);
And on clicking the tracker the below mentioned action method is triggered, which in turn calls a helper function:
Controller Code:
public class ClickTrackingController : Controller
{
[HttpGet]
public JsonResult Track(string query, string hitId, string trackId)
{
try
{
Helper.TrackClick(query, hitId, trackId);
return Json(new { msg = "Click tracked" }, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
}
}
}
Helper funtion code:
public static void TrackClick(string query, string hitId, string trackId)
{
SearchClient.Instance.Statistics().TrackHit(query, hitId, command =>
{
command.Hit.Id = hitId;
command.Id = trackId;
command.Ip = "10.0.0.250";
command.Tags = ServiceLocator.Current.GetInstance<IStatisticTagsHelper>().GetTags(false); // don't get all tags
command.Hit.Position = null;
});
}
If you see I am hard coding the HitType and using a helper method to get the PageGuid to assign the value to HitId. I was having the same problem as you have mentioned in your article:https://world.episerver.com/forum/developer-forum/EPiServer-Search/Thread-Container/2015/5/using-projections-with-hitid-and-hittype/. But since I use a view model I am not sure if I can use the approach in the article.
Also, the query string parameters are as shown below:
A sample URL looks like the one mentioned below:
http://localhost:2000/ClickTracking/Track?query=sample&hitId=ProjectName.Models.PageTypes.ArticlePage%2F94cb8651-9224-4531-b60d-29dc66eeba93&trackId=1B2M2Y8AsgTpgAmY7PhCfg%3D%3D
I had this issue recently and opened a support ticket for it. I was told that I needed a "SearchTitle" property in my index model, and that whatever I loaded into that property would be what showed in the statistics where I was seeing "Page not found". It worked! Maybe you need to do the same ?
Any luck with this? I have the same issue. I have added SearchTitle but it did nothing. :-/
Siddharth Gupta, Your problem might be that you hard coded "ArticlePage" instead of doing this;
HitType = SearchClient.Instance.Conventions.TypeNameConvention.GetTypeName(x),
also you might want to try this for your HitId;
SearchClient.Instance.Conventions.IdConvention.GetId(** the actual content (The articlePage)**)
Finally. Make sure your class has the property SearchTitle implemented as Dave pointed out.
Jens Qvist : Yes I got this working actually, and the problem was actually the fact that I was hard coding the HitType and the HitId as well was not implemented right. Let me know if you need a code snippet that will help you.
Nah, was the hitType for me aswell. It needs to match the type of the indexed object that is clicked :-)
Hi
Any more tips available for this one? I'm using the following to create the hit ID
string hitId = SearchClient.Instance.Conventions.IdConvention.GetId(x);
string hitType = SearchClient.Instance.Conventions.TypeNameConvention.GetTypeName(x.GetType());
string hitTrackId = $"{hitType}/{hitId}";
e.g. Namespace_Pages_MyPage/_ba434590-fd1a-4d8b-a99b-d821b9e5bb8f_en-NZ
I have a "SearchTitle$$string" populated in the EPi find index and I also have a number of click-through rates registered and bumping up the % but everything is coming through as "Page not found"
Only thing I'm wondering is if I can expect this to work correctly in a local dev environment or do the pages need to publicly available?
Thanks,
Jason
A little bit late to the party, just wanted to let anyone else know since I got it working with the built in "unifiedsearch"-style redirecting, for tracked links, using GetResult.
Meaning clicking a link with the below querystring-params (notice _t_ which matches the params defined here) applied will get you to the page and all tracked query params will be stripped from the url:
public string GetTrackedSearchUrl(string url)
{
if (string.IsNullOrEmpty(TrackId) || string.IsNullOrEmpty(HitId)) return url;
var initialSign = url?.Contains("?") == true ? "&" : "?";
var queryParams = string.Join("&", new[] {
GetQueryParam("id",TrackId),
GetQueryParam("q", Query),
GetQueryParam("hit.id", HitId),
GetQueryParam("hit.pos", HitPosition.ToString()),
GetQueryParam("tags", string.Join(",", Tags ?? Array.Empty<string>()))
});
return url + initialSign + queryParams;
}
private string GetQueryParam(string name, string value) =>
$"_t_{name}={HttpUtility.UrlEncode(value)}";
TrackId
is the id returned from the TrackQuery
()-call shown below.
HitId
is from the SearchHit<T> (returned from GetResult, $"{hit.Type}/{hit.Id}"
).
HitPosition
is just a counter offset byt the current skip-count for the query.
Tags
are the fetched tags from the call below.
The tracking is enabled in the following way:
private (bool tracked, string trackId, IEnumerable<string> tags) CheckQueryTracking(ISearch search, Domain.Models.SearchContext context, int totalMatching)
{
if (context?.Tracked == true)
{
var tags = _statisticsTagHelper.GetTags(false);
var result = search.Client.Statistics().TrackQuery(context.Query, x =>
{
x.Tags = tags;
x.Query.Hits = totalMatching;
});
return (true, result.TrackId, tags);
}
return (false, null, null);
}
_statisticsTagHelper
is a injected instance of IStatisticTagsHelper
. totalMatching
is fetched from GetResult
(.TotalMatching
).
It can probably can be simplified in a lot of ways for your use but we have some layers of transforming/IMapping etc meaning we store all "search shared"-props above.
This is what we do for each search hit:
TrackId = trackId,
Query = context.Query,
HitId = $"{hit.Type}/{hit.Id}",
HitPosition = ++pos,
Tags = tags,
For the redirecting to work find:s javascript needs to be loaded as well (/ClientResources/Epi/x.x.x/find.js).
I hope this helps someone else out!
In one environement we had an issue with the TrackContext-constructor (reflecting seems to point to HttpContext.Current.Session being null).
In this case update to a later version of find since it's fixed bug or you could construct your own TrackId (or temporarly setting HttpContext to null on a fallback call to TrackContext()).
// Magnus
I am trying to implement click tracking using EPiServer Find for a CMS application. I am able to generate the statistics but the page name in the search results is showing up as page not found.
Below is a screen shot for reference: https://www.screencast.com/t/ywkYtn9L
Any info on this will be of great help to me.