Blocking bots from creating contacts

Matt Larrabee asked on July 26, 2023 15:26

I have a Kentico 13 site that is creating ~3-5 contacts a second mostly from bot/scan traffic. I tried to implement ICurrentContactProvider to block these (or at least identify them all as the same contact). My code seems to work but when the Custom Contact provider is active, activities are not being tracked for any contacts. Here is the code I'm using for the contact provider implementation.

using System;
using CMS;
using CMS.Membership;
using CMS.ContactManagement;
using CMS.Base;
using Azure.Core;
using Microsoft.AspNetCore.Http;
using System.Linq;
using Microsoft.AspNetCore.Http.Extensions;
using DocumentFormat.OpenXml.Drawing.Charts;
using Microsoft.SqlServer.TransactSql.ScriptDom;

[assembly: RegisterImplementation(typeof(ICurrentContactProvider), typeof(CustomCurrentContactProvider))]


public class CustomCurrentContactProvider : ICurrentContactProvider
{
    private IHttpContextAccessor _httpContextAccessor;
    private IContactPersistentStorage _contactPersistentStorage;
    private IContactInfoProvider _contactInfoProvider;

    public CustomCurrentContactProvider(IHttpContextAccessor httpContextAccessor, IContactPersistentStorage contactPersistentStorage, IContactInfoProvider contactInfoProvider)
    {
        _httpContextAccessor = httpContextAccessor;
        _contactPersistentStorage = contactPersistentStorage;
        _contactInfoProvider = contactInfoProvider;
    }

    public ContactInfo GetCurrentContact(IUserInfo currentUser, bool forceUserMatching)
    {
        var userAgent = _httpContextAccessor?.HttpContext?.Request.Headers["User-Agent"].ToString();
        var currentURL = _httpContextAccessor?.HttpContext?.Request.GetDisplayUrl();

        ContactInfo contact = _contactPersistentStorage.GetPersistentContact(); 

        if(contact != null){

            return contact;
        }
        else
        {
            if (currentURL == null || currentURL.ToLower().Contains("health-check") || String.IsNullOrEmpty(userAgent) || userAgent.Contains("bot") || userAgent.Contains("probe") || !(new[] { "Chrome", "Safari", "Firefox" }.Any(c => userAgent.Contains(c))))
            {
                ContactInfo ct = ContactInfo.Provider.Get()
                                    .WhereEquals("ContactEmail", "bot@botcontact.com")
                                    .TopN(1)
                                    .FirstOrDefault();
                if (ct == null)
                {
                    //create bot user
                    ContactInfo nu = new ContactInfo();
                    nu.ContactEmail = "bot@botcontact.com";
                    nu.ContactFirstName = "Bot User";
                    _contactInfoProvider.Set(nu);

                    SetCurrentContact(nu);

                    return nu;
                }
                else
                {
                    SetCurrentContact(ct);
                    return ct;
                }
            }
            else
            {
                ContactInfo nu = new ContactInfo();
                nu.ContactFirstName = "Anonymous - "+DateTime.Now.ToLongDateString();
                _contactInfoProvider.Set(nu);

                SetCurrentContact(nu);

                return nu;
            }
        }
    }

    public ContactInfo GetExistingContact(IUserInfo currentUser, bool forceUserMatching)
    {
        ContactInfo contact = _contactPersistentStorage.GetPersistentContact();

        return contact;

    }

    public void SetCurrentContact(ContactInfo contact)
    {
        _contactPersistentStorage.SetPersistentContact(contact);
    }
}

Correct Answer

Matt Larrabee answered on September 5, 2023 14:20

Kentico support was able to give me a solution for this. Before setting the current contact with SetCurrentContact(nu) method, you need to set ContactMonitored to true for the contact: nu.ContactMonitored = true;

0 votesVote for this answer Unmark Correct answer

   Please, sign in to be able to submit a new answer.