Answer
It is possible to set this data on your own. It can be done as Gatogordo suggests, using the following code snippet.
Tracker.Current.Session.Interaction.SetGeoData(new WhoIsInformation
{ City = "Boston", Country= "US", Region = "North America" });
However, it's important to know how this data is initially collected in an out-of-the-box scenario.
Background Information for Sitecore Version 8+
Within Sitecore Analytics, if you do a search in your configs for UpdateGeoIpData, you'll find 4 pipelines with a processor to handle retrieving this information. Each pipeline cares a little differently depending on what's going on. UpdateGeoIpData()
on the Interaction
returns a bool
value depending on the success of gathering GeoIP data.
Those pipelines include:
- commitSession
<processor type="Sitecore.Analytics.Pipelines.CommitSession.UpdateGeoIpData, Sitecore.Analytics" patch:source="Sitecore.Analytics.Tracking.Database.config"/>
- This is the last line of defense in the system for making sure that GeoIP data can be recorded.
- createVisit
<processor type="Sitecore.Analytics.Pipelines.CreateVisits.UpdateGeoIpData, Sitecore.Analytics"/>
- This is making sure that the GeoData is set on the Interaction when the visit is first created.
- ensureClassification
<processor type="Sitecore.Analytics.Pipelines.EnsureClassification.UpdateGeoIpData, Sitecore.Analytics"/>
- This processor actually is a precursor processor for other functionality. It's purposes is to set the
ShouldClassificationBeGuessed
argument for the continuation of that pipeline. It utilizes !Tracker.Current.Interaction.UpdateGeoIpData();
as it's conditional statement. There is a side effect that in the envent the VisitData.GeoData
is null
, it will go ahead and attempt to set the geographical information. If the GeoData is present, it returns a fast true.
- startTracking
<processor type="Sitecore.Analytics.Pipelines.StartTracking.UpdateGeoIpData, Sitecore.Analytics"/>
- This processor initially populates the GeoData inSession Interaction on
Tracker.Current.Session
.
Specifically, these pipeline processes utilize Session.Interaction.UpdateGeoIpData(Timespan)
. Also important to note that Interaction is actually based off of CurrentInteraction
which is an abstract class. There are four out-of-the-box implementations of this class, of which CurrentVisitContext
is most commonly used:

Unfortunately, CurrentVisitContext
is NOT a class that can
easily be extended or overridden through Sitecore configuration
patching.
A Closer Look at the Start Tracking Processor
public class UpdateGeoIpData : StartTrackingProcessor
{
public override void Process(StartTrackingArgs args)
{
Assert.IsNotNull((object) Tracker.Current, "Tracker.Current is not initialized");
Assert.IsNotNull((object) Tracker.Current.Session, "Tracker.Current.Session is not initialized");
if (Tracker.Current.Session.Interaction == null)
return;
Tracker.Current.Session.Interaction.UpdateGeoIpData();
}
}
Notice it's a pretty simple processor. There is also an Expiry option for location data. Out of the box, the Expiry is turned off (hence TimeSpan.MaxValue
). However, this is an option.
Rolling Your Own - Overriding Default Functionality
To override default functionality and seed your own Geographical Data, I would create processors of your own, mimicking the 4 processors mentioned above. This would ensure that your custom implementation is not confused with the out-of-the-box.
An Example
public class CustomGeoIpData : StartTrackingProcessor
{
public override void Process(StartTrackingArgs args)
{
Assert.IsNotNull((object) Tracker.Current, "Tracker.Current is not initialized");
Assert.IsNotNull((object) Tracker.Current.Session, "Tracker.Current.Session is not initialized");
if (Tracker.Current.Session.Interaction == null)
return;
Tracker.Current.Session.Interaction.SetGeoData(new WhoIsInformation { City = "Boston", Country= "US", Region = "North America" });
}
}
By setting it here in startTracking
pipeline or createVisit
pipeline, all other instances, which utilize UpdateGeoIpData()
, will be ignored. This is because the very first thing UpdateGeoIpData()
does is a check to see if VistiData.GeoData is set, which SetGeoData()
does directly.
public override bool UpdateGeoIpData(TimeSpan timeout)
{
VisitData visitData = this.visitData;
if (visitData.GeoData != null)
return true;
... snipped code ....
return true;
}
Lastly, you can also run SetGeoIpData()
during the course of a visit through code, to overwrite the data previously set.