UPDATE 09-04-2020
The workaround below has worked fine, but I had to remove it due to a change to our Org which enforces unicity on e-mail address. Anyway, I figured out what the problem was with the embedded service deployment. It turns out it does actually work and you can create person-accounts from it.
The main problem in my case was that our chat is in Dutch and thus uses translated values for 'First Name', 'Last Name' and 'Email', the most important of which is 'Email' is written as 'E-mail'. The docs do say to use the label, but it does not mention anything about translated labels. So be really careful when you have a multi-lingual implementation.
The way I found this out is by debugging the script in my browser console, I then discovered the labels being passed are the literal labels as they are shown in the chat-form:

When I found that out, it was pretty straightforward writing the code for the prechat. The default case status was also set incorrectly due to translation issues.
This is the code, you can ignore the custom e-mail field I use, this is org specific. This code creates a personaccount if non exists and or if it is found it links the personcontact to the transcript and the personaccount as well, enabling chat history. I have not been able to connect the personcontact when it is newly created.
embedded_svc.settings.extraPrechatFormDetails = [{
"label": "RecordTypeId",
"value": "0120N000000Uwb8QAC",
"displayToAgent": false
},
{
"label": "CaseStatus",
"value": "Nieuw",
"displayToAgent": false
}];
embedded_svc.settings.extraPrechatInfo = [{
"entityName": "Contact",
"saveToTranscript": "ContactId",
"showOnCreate": true,
"entityFieldMaps": [{
"isExactMatch": false,
"fieldName": "FirstName",
"doCreate": false,
"doFind": false,
"label": "Voornaam"
}, {
"isExactMatch": false,
"fieldName": "LastName",
"doCreate": false,
"doFind": false,
"label": "Achternaam"
}, {
"isExactMatch": true,
"fieldName": "Email_GG__c",
"doCreate": false,
"doFind": true,
"label": "E-mail"
}]
},
{
"entityName": "Account",
"showOnCreate": true,
"linkToEntityName": "Case",
"linkToEntityField": "AccountId",
"saveToTranscript": "AccountId",
"entityFieldMaps": [
{
"isExactMatch": false,
"fieldName": "LastName",
"doCreate": true,
"doFind": false,
"label": "Achternaam"
},
{
"isExactMatch": false,
"fieldName": "RecordTypeId",
"doCreate": true,
"doFind": false,
"label": "RecordTypeId"
},
{
"fieldName": "PersonEmail",
"doCreate": true,
"label": "E-mail"
},
{
"doCreate": false,
"doFind": true,
"fieldName": "Email_GG__pc",
"isExactMatch": true,
"label": "E-mail"
}]
},
{
"entityName": "Case",
"showOnCreate": true,
"entityFieldMaps": [
{
"doCreate": true,
"doFind": false,
"fieldName": "Status",
"isExactMatch": false,
"label": "CaseStatus"
}]
}];
Old Answer:
After contacting Salesforce support I decided that I had no other option than to create an apex trigger for this to have a short term solution. The code might be a little rough and have room for improvement, but I thought I'd share it with you hoping it will help you a bit. Please let me know if you have any questions.
I created a 'before update' trigger on the livechattranscript object.
public void BeforeUpdate(List<SObject> newList, Map<Id, SObject> newItems, List<SObject> oldList, Map<Id, SObject> oldMap)
{
//change isolated contacts to person accounts
List<LiveChatTranscript> transcriptsForConversion = new List<LiveChatTranscript>();
List<Id> transcriptContactIds = new List<Id>();
for (LiveChatTranscript transcript : (List<LiveChatTranscript>)newList) {
if (transcript.ContactId != null && transcript.CaseId != null (transcript.ContactId != null && transcript.CaseId != null && transcript.AccountId == null) {
transcriptsForConversion.add(transcript);
transcriptContactIds.add(transcript.ContactId);
}
}
convertToPersonAccount(transcriptsForConversion, transcriptContactIds);
}
And this is the method that does the actual work:
//Converts the isolated contacts created for chat to person accounts
public static void convertToPersonAccount(List<LiveChatTranscript> chatTranscriptList, List<Id> transcriptContactIds){
List<LiveChatTranscript> transcriptsToUpdate = new List<LiveChatTranscript>();
List<Contact> contactsToRemove = new List<Contact>();
List<Account> newPersonAccounts = new List<Account>();
List<Case> casesToReassign = new List<Case>();
Map<Id, Account> contactIdToPersonAccMap = new Map<Id, Account>();
Map<Id, Contact> transcriptContactDetails;
//Get the correct record type id for personaccounts
String b2cRecordType = Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName().get('PersonAccount').getRecordTypeId();
//Retrieve additional needed attributes on the chat transcript
transcriptContactDetails = new Map<Id, Contact>([SELECT FirstName
, LastName
, Email
, AccountId
FROM Contact WHERE Id IN: transcriptContactIds]);
//Make sure to only handle change isolated contacts
for (LiveChatTranscript transcript : chatTranscriptList) {
if (transcript.ContactId != null && transcriptContactDetails.get(transcript.ContactId).AccountId == null) {
transcriptsToUpdate.add(transcript);
contactsToRemove.add(transcriptContactDetails.get(transcript.ContactId));
Account newPersonAcc = new Account(RecordTypeId = b2cRecordType,
FirstName = transcriptContactDetails.get(transcript.ContactId).FirstName,
LastName = transcriptContactDetails.get(transcript.ContactId).LastName,
PersonEmail = transcriptContactDetails.get(transcript.ContactId).Email
);
newPersonAccounts.add(newPersonAcc);
contactIdToPersonAccMap.put(transcript.ContactId, newPersonAcc);
}
}
insert newPersonAccounts;
//reassign the cases
casesToReassign = [SELECT AccountId, ContactId FROM Case WHERE ContactId IN :contactsToRemove];
for (Case reassignedCase : casesToReassign) {
reassignedCase.AccountId = contactIdToPersonAccMap.get(reassignedCase.ContactId).Id;
reassignedCase.ContactId = null;
}
//reassign cases and remove the no longer needed contacts
update casesToReassign;
delete contactsToRemove;
//reassign the chat
for (LiveChatTranscript transcript : transcriptsToUpdate) {
Account personAcc = contactIdToPersonAccMap.get(transcript.ContactId);
transcript.AccountId = personAcc.Id;
transcript.ContactId = null;
}
}