In my previous post I talked about an issue with enabling SSL and tracking Contacts in Kentico. The short story was simply disabling monitoring of on-line users. Now a new issue has come up, I have thousands of contacts I need to clean up.
As you've read in my previous post
I provide you the solution to stop these "ghost contacts" from being tracked on your site. What you may not know is has this bug been reported to Kentico and more importantly has it been fixed. The answer are Yes and well kinda...
If you don't know, Kentico has a 7-day bug fixing policy
. What this means is when you find a potential bug and report the issue, Kentico Developers verify it really is a bug, then they find a solution and a fix is typically put in place within 7 business days. More importantly, for me since it is somewhat of a game, is what's behind the 7-day bug fixing policy; for each bug that has been reported and fixed, a new tree is planted. Kentico calls this program, Trees For Bugs
This post isn't about Trees For Bugs or a bug fixing policy, it's about following up with what I've learned, what I've done to clean up the invalid contacts and what the "well kinda" answer is.
The "well kinda" answer is, I've been in contact with Kentico regarding this bug and they have verified it is a bug and it will be fixed. The problem is the solution Kentico has to fix the bug will cause some major breaking changes in version 9. So the will be released with the next major release of Kentico, version 10. So until Kentico releases version 10 the simple fix to stop recording these ghost contacts is to leave the "Monitor on-line users" option unchecked in Settings>Security & Settings>On-line Users.
Here is my fix to clean up the ghost contacts. I followed the instructions here
to create some stub code to create my own custom method for inactive contacts.
/// Custom implementation for deleting inactive/unnecessary contacts on a site.
class DeleteInactiveContacts : IDeleteContacts
/// Deletes contacts on a specific site.
/// <param name="site">The site on which the contacts are deleted.</param>
/// <param name="days">The number of days specified in the settings. Use the parameter if you want to delete contacts older than this number of days.</param>
/// <returns>The number of contacts that haven't been deleted.</returns>
public int Delete(SiteInfo site, int days, int batchSize)
if (site == null)
throw new ArgumentNullException("site");
var whereCondition = GetWhere(site);
var contacts = ContactInfoProvider.GetContacts().Source(item => item.LeftJoin<IPInfo>("ContactID", "IPOriginalContactID")).Where(whereCondition).TopN(batchSize);
foreach (var c in contacts)
/// Creates a where condition for the select statement
private string GetWhere(SiteInfo site)
var condition = new WhereCondition();
condition.And(new WhereCondition().WhereEquals("ContactSiteID", site.SiteID));
condition.And(new WhereCondition().Where("CONVERT(DATE, [ContactLastModified]) = CONVERT(DATE, [ContactCreated])"));
Code is pretty simple, it joins in the IP addresses table with the contacts and then simply deletes them. Remember this scheduled task has a new feature in version 9 and it will only run once per day during off-hours. So no matter how many times you execute it, it won't run until "off-hours". The way I was able to test this was to change the time on the computer to 230AM.
Hope this helps someone else out!
Good luck and happy coding!