Skip to main content
Solved

Hosted Page - Update Both Preferences and Unsubscribe

  • February 13, 2025
  • 5 replies
  • 62 views

Forum|alt.badge.img

I'm working on a Klaviyo hosted page where users can update their email preferences and unsubscribe from email marketing because I want customer to just click on unsubscribe page to do unsubscribe and update preference. However, I'm facing an issue:

  • If a user checks both $unsubscribe and nocatalog, Klaviyo only processes the unsubscribe action but doesn't update nocatalog.
  • I want the user to be able to update both preferences and unsubscribe at the same time.

Here's my current template that I edit from example code in https://help.klaviyo.com/hc/en-us/articles/115005077067 :

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Update Preferences</title>
    <style type="text/css">
        body {
            font-family: "Helvetica Neue", Arial, sans-serif;
            background-color: #f9f9f9;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        .form-container {
            background-color: #ffffff;
            padding: 40px;
            border-radius: 5px;
            box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
            width: 100%;
            max-width: 500px;
            text-align: center;
        }

        .form-container img {
            max-width: 100%;
            width: 300px;
            margin-bottom: 20px;
        }

        .form-container h1 {
            margin-bottom: 20px;
        }

        .form-container label {
            display: block;
            text-align: left;
            margin: 10px 0 5px;
            font-weight: bold;
        }

        .form-container input[type="text"],
        .form-container input[type="email"] {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 3px;
            font-size: 16px;
        }

        .form-container .checkbox-group {
            text-align: left;
            margin-top: 1rem;
        }

        .form-container .checkbox-group label {
            font-weight: normal;
            display: flex;
            align-items: center;
        }

        .form-container .checkbox-group input {
            margin-right: 8px;
        }

        .form-container button {
            width: 100%;
            padding: 12px;
            margin-top: 20px;
            font-size: 16px;
            color: #fff;
            background-color: #c13535;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }

        .form-container .unsubscribe {
            background-color: transparent;
            color: #282828;
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <form class="form-container" 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="nocatalog" />

        <h1>Update Preferences</h1>
        <label for="email">Email <span style="color: red;">*</span></label>
        <input type="email" name="$email" id="email"
            value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$email' }}{% else %}{{ person.email|default:'' }}{% endif %}"
            required />
        {% if form.errors|lookup:'$email' %}
        <p class="help-block">{% for error in form.errors|lookup:'$email' %}{{ error }}{% endfor %}</p>
        {% endif %}

        <label for="first-name">First Name <span style="color: red;">*</span></label>
        <input type="text" name="$first_name" id="first-name" value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$first_name' }}{% else %}{{ person.first_name|default:'' }}{% endif %}" required />

        <label for="last-name">Last Name <span style="color: red;">*</span></label>
        <input type="text" name="$last_name" id="last-name" value="{% if request.POST|lookup:'$email' %}{{ request.POST|lookup:'$last_name' }}{% else %}{{ person.last_name|default:'' }}{% endif %}" required />

        <div class="checkbox-group">
            <label><input type="checkbox" name="$unsubscribe" value="true"> Unsubscribe me from email marketing.</label>
            <label><input type="checkbox" name="nocatalog" value="true" {% if 'true' in person.nocatalog or 'true' in request.POST.nocatalog %}checked="checked" {% elif not person.nocatalog and not request.POST.nocatalog %}{% endif %} />Do not send me printed catalogs any longer.</label>
            <label><input type="checkbox" name="$double_optin" value="true"> Please include me more often for email messages.</label>
        </div>

        <button type="submit">Update Preferences</button>
    </form>
    <!-- /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>
        $(function() {
            $('#preferences_form').validate({
                rules: {
                    $email: {
                        required: true
                    }
                },
                messages: {
                    $email: 'Please enter your email address.',
                    $first_name: 'Please enter your first name.',
                    $last_name: 'Please enter your last name.'
                }
            });
            // Toggle validation based on selection.
            $('input[name="$unsubscribe"]').on('change', function() {
                $('form .form-actions button[type="submit"]').toggleClass('cancel', $(this).is(':checked'));
            });
        });
    </script>
</body>

</html>

 

Best answer by PatiphonO

emma.owens wrote:

Hi ​@PatiphonO ! 

Just following up on this - were you able to figure out how to set up the HTML so that it updates both preferences and unsubscribe at the same time? 

Yes, for unsubscribing, I just use the preset from Klaviyo, but for preference updates, I use JavaScript to check whether a checkbox is checked or not. If it is checked, I send an API request and wait for a response before submitting the form.

View original
Did this topic or the replies in the thread help you find an answer to your question?

5 replies

Christiannoerbjerg
Expert Problem Solver II
Forum|alt.badge.img+12

Hi ​@PatiphonO 

Thank you for posting in the Community!

I think the issue lies in how Klaviyo processes $unsubscribe actions—it treats it as a global opt-out, which may override other preference updates.

Can you confirm that your settings isn’t set to global unsubscription? :-) 

Christian Nørbjerg Enger
Partner & CPO
Web: Segmento.dk
LinkedIn: @christianfromsegmento
Voldbjergvej 22b, 8240 Risskov


Forum|alt.badge.img
  • Author
  • Contributor I
  • 2 replies
  • February 14, 2025
Christiannoerbjerg wrote:

Hi ​@PatiphonO 

Thank you for posting in the Community!

I think the issue lies in how Klaviyo processes $unsubscribe actions—it treats it as a global opt-out, which may override other preference updates.

Can you confirm that your settings isn’t set to global unsubscription? :-) 

Christian Nørbjerg Enger
Partner & CPO
Web: Segmento.dk
LinkedIn: @christianfromsegmento
Voldbjergvej 22b, 8240 Risskov

Where can I find that setting?


Adunni
Problem Solver II
Forum|alt.badge.img+1
  • Problem Solver II
  • 20 replies
  • February 14, 2025

Hi ​@PatiphonO ,

You're on the right path with your Klaviyo-hosted page, but the issue happens because Klaviyo prioritizes unsubscribing over updating custom profile properties. When $unsubscribe is checked, Klaviyo processes it first and doesn't update other preferences like nocatalog.

Solution: Ensure Both Actions Are Processed

To fix this, try these steps:

  1. Use a hidden input field to store nocatalog as a profile property before the form submission.

     

    html

    CopyEdit

    <input type="hidden" name="$fields" value="nocatalog" />

  2. Manually update the property after unsubscribing by adding a Klaviyo API call in JavaScript or using a separate request to ensure nocatalog is updated.

  3. Alternatively, create two separate actions:

    • First, update preferences (nocatalog and others).
    • Then, process the unsubscribe request separately.

Next Steps

If you need help refining your form or setting up the API request, let me know—I’d be happy to guide you through it! 🚀

Cheers,
Adunni


emma.owens
Community Manager
Forum|alt.badge.img+13
  • Community Manager
  • 64 replies
  • February 19, 2025

Hi ​@PatiphonO ! 

Just following up on this - were you able to figure out how to set up the HTML so that it updates both preferences and unsubscribe at the same time? 


Forum|alt.badge.img
  • Author
  • Contributor I
  • 2 replies
  • Answer
  • February 20, 2025
emma.owens wrote:

Hi ​@PatiphonO ! 

Just following up on this - were you able to figure out how to set up the HTML so that it updates both preferences and unsubscribe at the same time? 

Yes, for unsubscribing, I just use the preset from Klaviyo, but for preference updates, I use JavaScript to check whether a checkbox is checked or not. If it is checked, I send an API request and wait for a response before submitting the form.