For you case I suggest you to use Sitecore Data Exchange Framework.
You have to create your own facets, you set what fields you have to map, create scheduler tasks and configure how often to run. For all you will need to create custom code.
SubmitContact pipeline is used by :
// Sitecore.Analytics.Pipelines.SubmitContact.SubmitContactPipeline
public static void Run(SubmitContactArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (!XdbSettings.Enabled)
{
args.AbortPipeline();
return;
}
CorePipeline.Run("submitContact", args);
}
The method Run is used by :
// Sitecore.Analytics.Data.ContactRepository
public override bool SaveContact(Contact contact, ContactSaveOptions options)
{
Assert.ArgumentNotNull(contact, "contact");
Assert.ArgumentNotNull(options, "options");
ContactContext contactContext = (ContactContext)contact;
if (contactContext.IsTemporaryInstance)
{
contactContext = (ContactContext)this.MergeTemporaryContact(contactContext, options.LeaseOwner, System.TimeSpan.FromSeconds(10.0));
contactContext.IsTemporaryInstance = false;
}
if (!options.Release && options.LeaseOwner != null && contactContext.Contact.Lease == null)
{
System.DateTime expirationTime = System.DateTime.UtcNow + AnalyticsSettings.MaxAcceptedClockDeviation + options.LeaseDuration;
contactContext.Contact.Lease = new LeaseData
{
ExpirationTime = expirationTime,
Owner = options.LeaseOwner
};
}
SubmitContactArgs args = new SubmitContactArgs(contactContext, this.provider, true);
SubmitContactPipeline.Run(args);
if (this.provider.SaveContact(contactContext.Contact, options))
{
ProcessingReason reason = contactContext.IsNew ? ProcessingReason.Created : ProcessingReason.Updated;
this.ScheduleForProcessing(contactContext.Contact.Id.Guid, reason);
LeaseOwner leaseOwner = new LeaseOwner(AnalyticsSettings.ClusterName, LeaseOwnerType.WebCluster);
ID successorId = new ID(contact.ContactId);
System.Guid[] mergingSources = contact.GetMergingSources();
System.Guid[] array = mergingSources;
for (int i = 0; i < array.Length; i++)
{
System.Guid sourceContactId = array[i];
this.ObsoleteContact(sourceContactId, leaseOwner, successorId);
}
foreach (System.Collections.Generic.KeyValuePair<string, object> current in from pair in contact.Attachments
where pair.Value is IUpdatableObject
select pair)
{
this.provider.Update(current.Value as IUpdatableObject);
}
return true;
}
return false;
}