Skip to main content

Hi all,

I’m trying to have a custom unsubscribe page where i ask users the reason for their decision.

So besides the usual ‘unsubscribe’ button, I have a list asking users why they want to remove their email.

I followed the steps in here: https://help.klaviyo.com/hc/en-us/articles/115005077067-How-to-Custom-Code-an-Unsubscribe-or-Manage-Preferences-Page  to create a custom page.

I’ve also followed the steps here: https://help.klaviyo.com/hc/en-us/articles/115005074627-Guide-to-Properties to add custom properties when my users initially sign up.

So the way im trying this is:

  • I have a hidden input named ‘unsubscribed_reason’ when users sign up. (I have tried the same property with a $).
  • In my unsubscribe form, I (try) to send this property back with whichever option the user selects.
  • I would expect to see said property updated under the user profile after they have unsubscribed. This is the step im missing.

 

Example of my code matching the example code.

See my custom property named: ‘unsubscribed_reason’.

 

Problem is that my user profile is not being updated at all, so im not really sure of what im missing.


  • <input type="hidden" name="$fields" value="unsubscribe_reason" />
    <input type="hidden" name="$list_fields" value="unsubscribe_reason" />

    ....
    <div class="form-group">
    <label for="interests" class="col-sm-3 control-label">Please state your reason for unsubscribing:</label>
    <div class="col-sm-9">
    <div class="radio">
    <label>
    <!-- Default value. -->
    <input type="radio" name="unsubscribe_reason" value="received" {% if person.unsubscribe_reason == 'received' or request.POST.unsubscribe_reason == 'received' %}checked="checked"{% elif not person.unsubscribe_reason and not request.POST.unsubscribe_reason %}checked="checked"{% endif %} />
    I received too many emails
    </label>
    </div>
    <div class="radio">
    <label>
    <input type="radio" name="unsubscribe_reason" value="relevant" {% if person.unsubscribe_reason == 'relevant' or request.POST.unsubscribe_reason == 'relevant' %}checked="checked"{% endif %} />
    The content is not relevant to me
    </label>
    </div>
    <div class="radio">
    <label>
    <input type="radio" name="unsubscribe_reason" value="never" {% if person.unsubscribe_reason == 'never' or request.POST.unsubscribe_reason == 'never' %}checked="checked"{% endif %} />
    I have never subscribed to this mailing list
    </label>
    </div>
    <div class="radio">
    <label>
    <input type="radio" name="unsubscribe_reason" value="promotion" {% if person.unsubscribe_reason == 'promotion' or request.POST.unsubscribe_reason == 'promotion' %}checked="checked"{% endif %} />
    Signed up during a promotion and I am no longer interested
    </label>
    </div>
    <div class="radio">
    <label>
    <input type="radio" name="unsubscribe_reason" value="emails" {% if person.unsubscribe_reason == 'emails' or request.POST.unsubscribe_reason == 'emails' %}checked="checked"{% endif %} />
    Difficulty viewing emails on my device
    </label>
    </div>
    </div>
    </div>

     

 

Thanks!

Hi there @coljung,

Thanks for posting your question to the Community!

So unfortunately, Klaviyo does not currently offer services to help build out custom code, nor do we provide support for custom code troubleshooting. However, looking at your code I am not seeing any syntax errors that might be causing it. The custom property should appear as an option (as long as people have submitted responses) when trying to create a segment or create definitions. If it is not being pulled properly, I would speak with your developer to see if they can fix the code.

Apologies for the inconveniece,

Alex


Hi there @coljung,

Thanks for posting your question to the Community!

So unfortunately, Klaviyo does not currently offer services to help build out custom code, nor do we provide support for custom code troubleshooting. However, looking at your code I am not seeing any syntax errors that might be causing it. The custom property should appear as an option (as long as people have submitted responses) when trying to create a segment or create definitions. If it is not being pulled properly, I would speak with your developer to see if they can fix the code.

Apologies for the inconveniece,

Alex

Ok..

You guys provide an example here: https://help.klaviyo.com/hc/en-us/articles/115005077067-How-to-Custom-Code-an-Unsubscribe-or-Manage-Preferences-Page without actually explaining the code part properly.

I’m THE developer, and have trouble making any changes for that code work. The moment I change any of the variables, it stops working. I also checked with my backend devs and they are also confused.

I understand the ‘its a hosted page so we can’t help you’. But the one example you have isnt explained at all.

There are 2 confusing parts in your example code:

The hidden inputs are not explained and I have tried adapting them. To no avail.

<input type="hidden" name="$fields" value="EmailInterests,EmailFrequency" />
<input type="hidden" name="$list_fields" value="EmailInterests" />

 

Also, EmailFrequency seems to have some predefined values somewhere in your backend, so the moment i change those to my custom options, it stops working.

So, I dont expect you to provide me with a custom page.. but i need some guidance because your only example on how to achieve this has zero explanation.

 

Thanks

 


Hi @coljung,

Thank you for your feedback regarding our documentation. We apologize for the lack of clarity on our end and I have gone ahead and communicated to our docs team about that article you linked. Unsubscribe function does not support setting custom properties for profiles. The design in our documentation you had linked was only meant for preferences pages. But there is a workaround we can try.

The first step is to make the form execute custom javascript that would perform an identify call like below:

var target_popup = function() { 
_learnq.push(.'identify', {
'$email' : $('#email')m0].value,
'UnsubReason': $("input"name='UnsubReason']:checked").val() || ''
}]);
}

The form tag looks like this:

   <form action="" id="preferences_form" method="POST" role="form" class="form-horizontal" onsubmit="target_popup()">

For learnq to work we also had to add at the top this:

<script async 
type="text/javascript"
src="//static.klaviyo.com/onsite/js/klaviyo.js?company_id=??????"></script>

To note, for hosted pages feature to be enabled on a customer’s site, you would have to reach out to support to get assistance with this. I have gone ahead and made a ticket regarding this for you.

Thank you again for bringing insight regarding this issue and I hope that we can reach a solution.

Alex


Hello and sorry for the delay.

Because of the holidays i postponed a bit working on this again, but I tried again yesterday.

I tried your code, did a bunch of tests… and still have a few issues.

 

So, here is the link to the unsubscribe page we have in case you can directly test: http://na-730.myklpages.com/p/unsubscribe?a=Krv55B&c=01FR1HKA4T3VTAAW7Z4ZF88ZXH&k=e6ea1da6e46eba8508a91239c76588ef&g=ND74u9&m=VF34Hi&r=5Swk3cU

 

A few things are happening. If you have some adblocker enabled, it wont load some of the scripts.

Once I disabled mine, page loaded without errors.

But then when i submit the form, im getting a bunch of errors that seem out of my control:

 

 

Last point, you had mentioned creating a ticket regarding this, which was 22 days ago. So far I have not been contacted in any way from anyone from Klaviyo regarding this issue.

 

Thanks a lot again and any help will be greatly appreciated.

P.

 

 

 

 


@coljung I found a workaround for this -- I’m not a developer but maybe this will help you?

 

I had the same issue: when I created the custom unsubscribe page, and added a list of reasons to select why they are unsubscribing, the custom profile property would not update once a user unsubscribed.

Therefore, the user would unsubscribe, but the unsubscribe reason would not post to their account as a custom profile property.

I used a lot of trial and error to come to the conclusion to treat the page with the idea of a multi-submit form -- but then actually splitting the two sections (unsubscribe reason selection and unsubscribe checkbox) into two separate forms, where upon submitting the first form reveals the second. Because of this, the unsubscribe reason selection must come first. rNOTE: I used Klaviyo’s base code for custom unsubscribe page, found here: https://help.klaviyo.com/hc/en-us/articles/115005077067-How-to-Custom-Code-an-Unsubscribe-or-Manage-Preferences-Page ]:

  • Add the unsubscribe reason selection in one <form> and the actual unsubscribe checkbox in a separate <form>; Note: both forms will need the email field (I just changed the label for the second one to “Confirm email address”)
  • The unsub reason form will have to come first
  • After the unsub reason form, put in a hidden iframe:
<iframe name='formresponse' width='300' height='200' style="display:none"></frame>
  • The unsub reason form then needs to have a target of the iframe, so add target=”formresponse” to your unsub reason form
  • To make it extra user-friendly, I also added an onclick to the unsub reason form button so that onclick it would hide the unsub reason form (put it in a div, used javascript function to hide on click), as well as to reveal the unsubscribe checkbox form (so it’s hidden until they submit their unsubscribe reason) (put the unsubscribe checkbox form in a div, used javascript function to reveal on click)

So change unsub reason form button to:

                 

<button type="submit" class="btn btn-default btn-primary" onclick="HideTop();ReasonSubmit()">Send</button>

 

And in the script add:
 

        function ReasonSubmit() {
    document.getElementById("UnsubDiv").style.display = "";
        }
         
         function HideTop() {
  var x = document.getElementById("hideDIV");
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}

 

Surround the unsub reason form with <div id=”hideDIV”>
Make sure to start the div just before the unsub reason form, and don’t forget to close off the div (</div) AFTER the unsub reason form only.

 

Surround the unsub checkbox form with <div id=”UnsubDiv”>
Make sure to start the div just before the unsub checkbox form, and don’t forget to close off the div (</div) AFTER the unsub checkbox form only.

 

Here is the FULL HTML, it’s Klaviyo’s example edited to include the above; but PLEASE NOTE that because of my trial and error, there may be some unnecessary code in there because I’m a novice -- it’s working fine for me though! Now I have created segments in Klaviyo where the properties equal each of the Unsubscribe reasons so I can see why people are unsubscribing. :D 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style type="text/css">
/* Space out content a bit */
body {
padding-top: 20px;
padding-bottom: 20px;
padding-left: 20px;
padding-right: 20px;
font-family: 'Neue Helvetica', sans-serif;
}

form {
margin-bottom: 18px;
}

/* Custom page header */
.header {
border-bottom: 1px solid #e5e5e5;
margin-bottom: 10px;
}

.header h1 {
margin: 10px 0;
font-size: 24px;
}

.required-fields {
text-align: right;
}

.required-fields span {
color: #a94442;
font-weight: bold;
}

.list-group-item label {
font-weight: normal;
margin-top: 17px;
}

.list-group-item label input type="checkbox"] {
margin-right: 4px;
}

.form-group span.required {
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #a94442;
font-weight: bold;
user-select: none;
}

.label.error {
color: #a94442;
font-weight: bold;
margin-top: 4px;
}

.form-actions {
margin: 25px 0;
}

.form-control+.form-control {
margin-top: 6px;
}

.panel-group .panel-title .closed-icon,
.panel-group .panel-title .open-icon {
margin-right: 0.5em;
top: 2px;
}

.panel-group .panel-title a:hover,
.panel-group .panel-title a:active {
text-decoration: none;
}

.panel-group .panel-title a:hover .text,
.panel-group .panel-title a:active .text {
text-decoration: underline;
}

.panel-group .panel-title .closed-icon {
display: none;
}

.panel-group.closed .panel-title .open-icon {
display: none;
}

.panel-group.closed .panel-title .closed-icon {
display: inline;
}

.btn {
border-radius: 0;
border: none;
background-color: black;
}

.btn:hover {
background-color: black;
}

/* Custom page footer */
.footer {
padding-top: 18px;
border-top: 1px solid #e5e5e5;
}

/* Customize container */
@media (min-width: 768px) {
.container {
max-width: 730px;
}
}
</style>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--Aif lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<!=endif]-->
</head>
<body>
<div class="container">
<div class="header">
<!-- Custom logo (add logo image as asset in Klaviyo, add name below where it says logo.png* -->
<img src="{% asset_url 'logo.png' %}" width="300px" />
<h1 style="color: black;">Unsubscribe from newsletters</h1>
<br>
</div>
<div>
&nbsp;
</div>
<div id="hideDIV">
<form action="" id="preferences_form" method="POST" role="form" class="form-horizontal" target="formresponse">
{% if form.non_field_errors %}
<div class="alert alert-danger">
{% for error in form.non_field_errors %}
{{ error }}{% if not forloop.last %}<br />{% endif %}
{% endfor %}
</div>
{% endif %}
<input type="hidden" name="$fields" value="EmailInterests,EmailFrequency,UnsubscribeReason" />
<input type="hidden" name="$list_fields" value="EmailInterests" />
<!-- <input type="hidden" name="$unsubscribed_url" value="/p/preferences_updated" /> -->
<!-- <input type="hidden" name="$updated_profile_url" value="/p/preferences_updated" /> -->
<!--<p class="required-fields">
<span>*</span> Required Information
</p>-->
<div class="form-group{% if form.errors|lookup:'$email' %} has-error{% endif %}">
<label for="email" class="col-sm-3 control-label">Email Address<span class="required">*</span></label>
<div class="col-sm-9">
<input type="email" class="form-control" id="email" name="$email" value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$email' }}{% else %}{{ person.email|default:'' }}{% endif %}" />
{% if form.errors|lookup:'$email' %}
<p class="help-block">{% for error in form.errors|lookup:'$email' %}{{ error }}{% endfor %}</p>
{% endif %}
</div>
</div>
<div class="form-group">
<label for="first_name" class="col-sm-3 control-label">First Name (optional)</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="first_name" name="$first_name" value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$first_name' }}{% else %}{{ person.first_name|default:'' }}{% endif %}" />
</div>
</div>
<div>
&nbsp;
</div>
<div id="reasons">
<div class="form-group">
<label for="UnsubscribeReason">Please tell us why you're unsubscribing (we want to learn and do better)!</label>
<div class="radio" id="reason-1" required>
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_1" value="Unwanted" required {% if person.UnsubscribeReason == 'Unwanted' or request.POST.UnsubscribeReason == 'Unwanted' %}checked="checked"{% endif %} />I don't remember subscribing/didn't want to subscribe.</label>
</div>
<div class="radio">
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_2" value="Unexpected Subjects" {% if person.UnsubscribeReason == 'Unexpected Subjects' or request.POST.UnsubscribeReason == 'Unexpected Subjects' %}checked="checked"{% endif %} />What I've received wasn't the type of emails I expected from you.</label>
</div>
<div class="radio">
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_2" value="Too Many" {% if person.UnsubscribeReason == 'Too Many' or request.POST.UnsubscribeReason == 'Too Many' %}checked="checked"{% endif %} />I've received too many emails from you.</label>
</div>
<div class="radio">
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_3" value="Discount Code Only" {% if person.UnsubscribeReason == 'Discount Code Only' or request.POST.UnsubscribeReason == 'Discount Code Only' %}checked="checked"{% endif %} />I only wanted the discount code.</label>
</div>
<div class="radio">
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_4" value="Too Expensive" {% if person.UnsubscribeReason == 'Too Expensive' or request.POST.UnsubscribeReason == 'Too Expensive' %}checked="checked"{% endif %} />Not in my budget.</label>
</div>
<div class="radio">
<label>
<input type="radio" name="UnsubscribeReason" id="unsubscribe_reason_5" value="Other" {% if person.UnsubscribeReason == 'Other' or request.POST.UnsubscribeReason == 'Other' %}checked="checked"{% endif %} />Other</label>
</div>
</div>
</div>
<div class="clearfix form-actions">
<div class="pull-right">
<button type="submit" class="btn btn-default btn-primary" onclick="HideTop();ReasonSubmit()">Send</button>
</div>
</div>
</form>
</div>
<iframe name='formresponse' width='100%' height='auto' style="display:none"></iframe>
<div id="UnsubDiv" style="display:none">
<form action="" id="preferences_form" method="POST" role="form" class="form-horizontal">
{% if form.non_field_errors %}
<div class="alert alert-danger">
{% for error in form.non_field_errors %}
{{ error }}{% if not forloop.last %}<br />{% endif %}
{% endfor %}
</div>
{% endif %}
<input type="hidden" name="$fields" value="EmailInterests,EmailFrequency,UnsubscribeReason" />
<input type="hidden" name="$list_fields" value="EmailInterests" />
<!-- <input type="hidden" name="$unsubscribed_url" value="/p/preferences_updated" /> -->
<!-- <input type="hidden" name="$updated_profile_url" value="/p/preferences_updated" /> -->
<!--<p class="required-fields">
<span>*</span> Required Information
</p>-->
<div class="form-group">
<p>
<p style="font-weight:normal"><b style="color:red">One last step!</b> Click below to confirm you would like to unsubscribe from all newsletters and notifications about sales, new launches, etc. (This doesn't include order and shipping confirmations and the like.) We're sorry to see you go!</p>
<div class="form-group{% if form.errors|lookup:'$email' %} has-error{% endif %}">
<label for="email" class="col-sm-3 control-label">Confirm Email Address<span class="required">*</span></label>
<div class="col-sm-9">
<input type="email" class="form-control" id="email" name="$email" value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$email' }}{% else %}{{ person.email|default:'' }}{% endif %}" />
{% if form.errors|lookup:'$email' %}
<p class="help-block">{% for error in form.errors|lookup:'$email' %}{{ error }}{% endfor %}</p>
{% endif %}
</div>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="unsubscribe" name="$unsubscribe" value="true" checked/>
<span class="text"><b>Unsubscribe me from all emails</b></span>
</label>
</div>
<div class="clearfix form-actions">
<div class="pull-right">
<button type="submit" class="btn btn-default btn-primary">Unsubscribe</button>
</div>
</div>
</div>
</form>
</div>
<footer class="footer">
<p>
© 2022 Your Company Inc. — <a href="https://www.google.ca/" target="_blank">Privacy Policy</a>
</p>
</footer>
</div>
<!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.13.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(function() {
$('#preferences_form').validate({
rules: {
$email: {
required: true
}
},
messages: {
$email: 'Please enter your email address.',
$first_name: 'Please enter your first name.',
}
});
// Toggle validation based on selection.
$('input name="$unsubscribe"]').on('change', function() {
$('form .form-actions button"type="submit"]').toggleClass('cancel', $(this).is(':checked'));
});
});



// Listen for click on toggle checkbox
$('#select-none-2').click(function(event) {
if(this.checked) {
// Iterate each checkbox
$('#select-none, #select-off, #select-off-2, #select-off-3, #select-off-4').each(function() {
this.checked = false;
});
}
});

$('#select-none').click(function(event) {
if(this.checked) {
// Iterate each checkbox
$('#select-none-2, #select-off, #select-off-2, #select-off-3, #select-off-4').each(function() {
this.checked = false;
});
}
});

$('#select-all').click(function(event) {
if(this.checked) {
// Iterate each checkbox
$('#select-off, #select-off-2, #select-off-3, #select-off-4').each(function() {
this.checked = true;
});
}
});

var unsubscribe = document.getElementById('unsubscribe');
var reason_div = document.getElementById('reason');
unsubscribe.onclick = function() {
console.log(this);
if(this.checked) {
reason_div.style 'display'] = 'block';
} else {
reason_div.stylee'display'] = 'none';
} if(this.unchecked) {
reason_div.stylel'display'] = 'none';
}
};

function ReasonSubmit() {
document.getElementById("UnsubDiv").style.display = "";
}

function HideTop() {
var x = document.getElementById("hideDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
</body>
</html>

Hope this helps!!


Hi @bricatfree,

Were you able to track the default Klaviyo’s Unsubscribe event within the UnsubDiv form?
If yes, please guide me on how to track it.
I really appreciate any help you can provide.
Dang


Reply