Personalization String Troubleshooting
Personalization strings are made up of percent signs combined with an attribute's column name, such as %%FirstName%%. When the email is sent, it is validated and each personalization string is rendered.
WHEN WE BUILT AN EMAIL , WE USE EMAIL PERSONALIZATION STRING EXTENSIVELY. IT'S RECOMMENDED TO USE LOOKUP FUNCTION INSTEAD OF EMAIL PERSONALIZATIONS.
WHY EMAILS ARE NOT SENT ? 👇
One of the most common use case is HARD ERROR. Hard error occurs due to various reasons :
- Suppression list
- List Detective
- Exclusion list
- Personalization
First 3 are very easy to troubleshoot :
Go to the journey, point to the email activity, under the email activity, click on the view contact details , open email summary activity, click on the link to Summary and navigate to the hard error tab.
You find the below details:
Personalization Issue is the most difficult process of troubleshooting
I have built these content block to troubleshoot the the personalization issue: PERSONALIZATIONLOG
<script runat="server">
Platform.Load("Core","1.1.1");
try{
</script>
%%[
IF EMPTY(@PERSONALIZATIONSTRING) THEN
SET @ERROROCCURRED='TRUE'
ENDIF
]%%
<script runat="server">
var ERROROCCURRED= Variable.GetValue("@ERROROCCURRED");
if(ERROROCCURRED=='TRUE'){
var PERSONALIZATIONSTRING= Variable.GetValue("@PERSONALIZATIONSTRING");
var PERSONALIZATIONSTRINGNAME=Variable.GetValue("@PERSONALIZATIONSTRINGNAME");
var SUBSCRIBERKEYVALUE=Variable.GetValue("@SUBSCRIBERKEYVALUE");
var JOBIDVALUE=Variable.GetValue("@JOBIDVALUE");
var LOGERRORDE= DataExtension.Init("PERSONALIZATIONLOG");
var ERRORMESSAGE='ERRORMESSAGE';
var ISEMAILSENT='ISEMAILSENT';
var ERRORAPICODE='ERRORCODE';
var ERRORNUMBER='ERRORNUMBER';
var SUBSCRIBERKEY='SUBSCRIBERKEY';
var JOBID='JOBID';
if(PERSONALIZATIONSTRING=='')
{
var MESSAGE=PERSONALIZATIONSTRINGNAME+' MISSING';
var ERRORTYPE='VALIDATION';
var ERRORCODE='500';
LOGERRORDE.Rows.Add({
SUBSCRIBERKEY:SUBSCRIBERKEYVALUE,
ERRORMESSAGE:ERRORMESSAGE,
ISEMAILSENT:ISEMAILSENT,
ERRORCODE:ERRORCODE,
ERRORNUMBER:ERRORNUMBER,
JOBID:JOBIDVALUE}
);
}
}
}
catch(e){
var SUBSCRIBERKEYVALUE=Variable.GetValue("@SUBSCRIBERKEYVALUE");
var JOBIDVALUE=Variable.GetValue("@JOBIDVALUE");
var ERRORMESSAGE=e.message;
var ERRORTYPE='EXCEPTION';
var ERRORCODE='501';
LOGERRORDE.Rows.Add({
SUBSCRIBERKEY:SUBSCRIBERKEYVALUE,
ERRORMESSAGE:ERRORMESSAGE,
ISEMAILSENT:ISEMAILSENT,
ERRORCODE:ERRORCODE,
ERRORNUMBER:ERRORNUMBER,
JOBID:JOBIDVALUE}
);
}
</script>
%%[
SET @LOGERRORDE='PERSONALIZATIONLOG'
SET @ERRORMESSAGE='ERRORMESSAGE'
SET @ISEMAILSENT='ISEMAILSENT'
SET @ERRORAPICODE='ERRORCODE'
SET @ERRORNUMBER='ERRORNUMBER'
SET @SUBSCRIBERKEY='SUBSCRIBERKEY'
SET @SUBSCRIBERKEYVALUE=_subscriberkey
SET @JOBIDVALUE=JOBID
SET @JOBID='JOBID'
IF EMPTY(@PERSONALIZATIONSTRING) THEN
SET @MESSAGE=CONCAT(@PERSONALIZATIONSTRINGNAME,' MISSING')
SET @ERRORTYPE='VALIDATION'
SET @ERRORCODE=500
RaiseError(@MESSAGE, FALSE,@ERRORTYPE,@ERRORCODE,1)
ENDIF
]%%
BUILD A TROUBLESHOOTING EMAIL AND PASTE THE BELOW CODE SNIPPET : PERFORM PREVIEW & TEST
Preview & Test with those subscribers you did not receive email. Recommend you to add your own personalization and test. Below code snippet checks email personalization that is reserved by SFMC.
%%[
SET @PERSONALIZATIONSTRING=_subscriberkey
SET @PERSONALIZATIONSTRINGNAME='SUBSCRIBERKEY'
]%%.
%%=ContentBlockbyKEY("PERSONALIZATIONLOG")=%%
%%[
SET @PERSONALIZATIONSTRING=emailaddr
SET @PERSONALIZATIONSTRINGNAME='EMAIL ADDRESS'
]%%.
%%=ContentBlockbyKEY("PERSONALIZATIONLOG")=%%
%%[
SET @PERSONALIZATIONSTRING=_emailid
SET @PERSONALIZATIONSTRINGNAME='EMAIL ID'
]%%.
%%=ContentBlockbyKEY("PERSONALIZATIONLOG")=%%
%%[
SET @PERSONALIZATIONSTRING=emailname_
SET @PERSONALIZATIONSTRINGNAME='EMAIL NAME'
]%%.
%%=ContentBlockbyKEY("PERSONALIZATIONLOG")=%%
TO FIND OUT WHO DID NOT RECEIVED EMAIL
RAISE ERROR :
All 5 parameters are important while calling RaiseError function. By default the 2nd parameter is set to "false".
Which means you are aborting all sends and the trigger send will stop the send.
If you set it to "True" , you are skipping the current send for the subscriber
whose personalization is not available currently.
DETERMINE WHETHER TO SKIP THE SUBSRIBER OR ABORT :
MAKE THE DECISION IN RUNTIME
%%[
SET @RAISE_ERROR = IIF(NOT EMPTY(@PERSONALIZATIONSTRING), 'FALSE', 'TRUE')
SET @SEND_EMAIL = IIF(EMPTY(@ISMANDATORY), 'TRUE', 'FALSE')
IF (@RAISE_ERROR=='TRUE') THEN
SET @MESSAGE=CONCAT(@PERSONALIZATIONSTRINGNAME,' IS MISSING')
RaiseError(@MESSAGE,@SEND_EMAIL,'VALIDATION ERROR',3,1)
ENDIF
]%%
IF ITS MANDATORY FOR ALL SEND AND IS CRITICAL TO BUSINESS :
%%[
SET @PERSONALIZATIONSTRING=emailaddr
SET @PERSONALIZATIONSTRINGNAME='EMAIL ADDRESS'
SET @ISMANDATORY='YES'
]%%
%%=ContentBlockbyKEY("PERSONALIZATIONERROR")=%%
%%[
SET @PERSONALIZATIONSTRING=_subscriberkey
SET @PERSONALIZATIONSTRINGNAME='SUBSCRIBERKEY'
SET @ISMANDATORY='YES'
]%%
%%=ContentBlockbyKEY("PERSONALIZATIONERROR")=%%
%%[
SET @PERSONALIZATIONSTRING=emailname_
SET @PERSONALIZATIONSTRINGNAME='EMAIL NAME'
SET @ISMANDATORY='YES'
]%%
%%=ContentBlockbyKEY("PERSONALIZATIONERROR")=%%
%%[
SET @PERSONALIZATIONSTRING=memberid
SET @PERSONALIZATIONSTRINGNAME='MEMBERID'
SET @ISMANDATORY='YES'
]%%
%%=ContentBlockbyKEY("PERSONALIZATIONERROR")=%%
IF NOT MANDATORY FOR ALL SEND AND WANT TO SKIP FOR THE CURRENT SUBSCRIBER :
IF MARKET DECIDES TO SKIP ONLY THOSE WHO CONTAINS BAD DATA
%%[
SET @PERSONALIZATIONSTRING=emailaddr
SET @PERSONALIZATIONSTRINGNAME='EMAIL ADDRESS'
// SET @ISMANDATORY='YES' // SKIP THE SEND FOR THIS USER
]%%
%%=ContentBlockbyKEY("PERSONALIZATIONERROR")=%%
HOW TO LOG PERSONALIZATION ERRORS INTO A LOGGING DE :
NOTE: Because the system pre-processes and builds these emails, tracking and reporting numbers include these emails despite the errors and may cause inaccuracies. Use this function to handle the errors of a small number of subscribers, rather than as a method to segment out large numbers of subscribers. Instead, use query activities and exclusion lists to handle your segmentation needs.
BEFORE YOU START YOUR JOURNEY SENDS, RUN THIS AS SSJS SCRIPT ACTIVITY IN AUTOMATION : 👇
<script runat="server">
Platform.Load("Core","1.1.1");
var PERSONALIZATIONLOGDE= DataExtension.Init("PERSONALIZATIONLOGDE");
var subscriberkey,firstName,lastName,email;
var config = {
name: "TargetDataExtensionName",
cols: ["Email", "SubscriberKey", "First_Name", "Last_Name"],
filter: {
LeftOperand:{
Property:"SubscriberKey",
SimpleOperator: "isNotNull",
Value: " "
}
,
LogicalOperator:"AND",
RightOperand:{
Property:"EmailConsent",
SimpleOperator:"equals",
Value:"True"
}
}
}
var records = retrieveRecords(config);
try{
if (records.length>0){
for(var i=0;i<records.length;i++){
subscriberkey=records[i].Subscriber_Key;
if(!subscriberkey){
PERSONALIZATIONLOGDE.Rows.Add({
ERRORMESSAGE:"Subscriberkey is missing",ERRORCODE:'303',ERRORTYPE:'Validation',SUBSCRIBERKEY:subscriberkey}
);
}
firstName=records[i].First_Name;
if(!firstName){
PERSONALIZATIONLOGDE.Rows.Add({
ERRORMESSAGE:"First Name is missing",ERRORCODE:'303',ERRORTYPE:'Validation',SUBSCRIBERKEY:subscriberkey}
);
}
lastName=records[i].Last_Name;
if(!lastName){
PERSONALIZATIONLOGDE.Rows.Add({
ERRORMESSAGE:"Last Name is missing",ERRORCODE:'303',ERRORTYPE:'Validation',SUBSCRIBERKEY:subscriberkey}
);
}
email=records[i].Email_Consent;
if(!email){
PERSONALIZATIONLOGDE.Rows.Add({
ERRORMESSAGE:"Email is missing",ERRORCODE:'303',ERRORTYPE:'Validation',SUBSCRIBERKEY:subscriberkey}
);
}
}
}
}
catch(e){
PERSONALIZATIONLOGDE.Rows.Add({
ERRORMESSAGE:e.message,ERRORCODE:'404',ERRORTYPE:'Exception',SUBSCRIBERKEY:subscriberkey}
);
}
function retrieveRecords(config) {
var prox = new Script.Util.WSProxy();
var records = [],
moreData = true,
reqID = data = null;
while (moreData) {
moreData = false;
if (reqID == null) {
data = prox.retrieve("DataExtensionObject[" + config.name + "]", config.cols, config.filter);
}
else {
data = prox.getNextBatch("DataExtensionObject[" + config.name + "]", reqID);
}
if (data != null) {
moreData = data.HasMoreRows;
reqID = data.RequestID;
for (var i = 0; i < data.Results.length; i++) {
var result_list = data.Results[i].Properties;
var obj = {
};
for (k in result_list) {
var key = result_list[k].Name;
var val = result_list[k].Value
if (key.indexOf("_") != 0) obj[key] = val;
}
records.push(obj);
}
}
}
return records;
}
</script>
USE DECISION SPLIT OR FILTER OUT THESE RECORDS BEOFRE EMAIL ACTIVITY IN JOURNEY BUILDER. ☝
Comments
Post a Comment