Support » Plugin: OneSignal - Web Push Notifications » Category wise subscription

  • Hi,

    Is it possible to a user can subscribe based on category? – that category will be stored as user tags.

    So, the message can be delivered based on category wise.

Viewing 3 replies - 1 through 3 (of 3 total)
  • Hi!

    Yes, I got it working last week.
    Though it requires some custom code to get it working.
    What I did is that I set up a new segment for every category that I got on my site.
    The segment uses the same name as the category and the user tag must be the slug name.
    Example segment: News, user tag: news, condition: {is} true.

    Then I added this piece of code in my functions.php in a child theme.

    /**
    * Send notifications based on category, Onesignal
    */
    
    add_filter('onesignal_send_notification', 'onesignal_send_notification_filter', 10, 4);
    
    function onesignal_send_notification_filter($fields, $new_status, $old_status, $post)
    {
        $categories = get_the_category($post->ID);
    
        // Change which segment the notification goes to, will always be the first category
        $fields['included_segments'] = array($categories[0]->name);
        return $fields;
    }

    I never use several categories for a post so this code works fine for me, you might need to change it if u select more than one category per post.

    So now that the push is being sent to the correct segment, users need to be able to choose which category they want to subscribe to.
    I solved this by adding a modal with a checkbox for each category.
    Added the code below to my footer.php, so that I could call/set a-href to the modal wherever I wanted. (I’m using bootstrap and FontAwesome, you will need to change this code if you don’t)

        <!--subscribe-->
    <div class="modal fade" id="subscribe-modal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
      <div class="modal-dialog">
            <div class="subscribemodal-container">
                <h2 class="text-center"><?php esc_html_e('Subscribe to push notifications', 'sjalvservice'); ?></h2>
                <p class="text-center"><?php esc_html_e('Choose the categories you want to subscribe to', 'sjalvservice'); ?></p>
                <form action="" method="post" name="subscribeform">
                    <div class="form-field">
                        <ul class="list-group">
    
                            <?php
    
                                $categories = get_categories();
                                foreach( $categories as $category ) {
    
                                    echo '<li class="list-group-item">' . esc_html( $category->name ) . '<div class="material-switch pull-right"><input id="subscribeSwitch' . esc_html( $category->slug ) . '" class="subscribecheckbox" value="' . esc_html( $category->slug ) . '" type="checkbox"/><label for="subscribeSwitch' . esc_html( $category->slug ) . '" class="label-success"></label></div></li>';
    
                                }
    
                            ?>
    
                        </ul>
    
                        <p id="subscribe-message"></p>
    
                        <a href="#" id="subscribe-submit"></a>
                    </div>
                </form>           
            </div>
        </div>
    </div>
    
    <!--   subscribe-message styling and localization.   -->
    <style>
    
        #subscribe-message.subscribed, #subscribe-message.unsubscribed, #subscribe-message.subupdated, #subscribe-message.choosecategory {
            opacity: 1;
        }
    
        #subscribe-message.subscribed:after {
            content: "<?php  esc_html_e('Click on allow notifications to confirm subscription!', 'sjalvservice'); ?>" !important;
        }
    
        #subscribe-message.unsubscribed:after {
            content: "<?php esc_html_e('You are now unsubscribed!', 'sjalvservice'); ?>" !important;
        }
    
        #subscribe-message.subupdated:after {
            content: "<?php esc_html_e('Subscription updated!', 'sjalvservice'); ?>" !important;
        }
    
        #subscribe-message.choosecategory:after {
            content: "<?php esc_html_e('Choose at least one category!', 'sjalvservice'); ?>" !important;
        }
    
        #subscribe-submit:after {
            content: "<?php esc_html_e('Subscribe', 'sjalvservice'); ?>";
        }
        
        #subscribe-submit.unsubscribe:after {
            content: "<?php esc_html_e('Change/unsubscribe', 'sjalvservice'); ?>" !important;
        }
    
    </style>
    

    As you can see I also added some css to a few classes, this will be used later to display a message to the subscriber.
    With the code above, I can add this line wherever I want in the theme:
    <a href="#subscribe-modal" id="subscribe-button" data-toggle="modal" title="Push notifications" style="display: none;"><i class="fa fa-lg fa-bell" aria-hidden="true"></i></a>

    So, now the only thing that remains is the logic behind all this, we need to fetch the checkboxes selected when the user push subscribe, and also send the tags to onesignal.

    This is done with javascript(should be added to the child-themes .js file), based on the OneSignal documentation, can probably be cleaned up a bit but this is what I’ve got and it works for me :

    /* Push notifications */
    
        function onManageWebPushSubscriptionButtonClicked(event) {
            
            var submessage = document.getElementById('subscribe-message');
            var items = document.getElementsByClassName('subscribecheckbox');
    		var selectedItems = {};
            var checked = false;
    		for(var i=0; i<items.length; i++){
    			if(items[i].type=='checkbox' && items[i].checked==true) {
                    
    				selectedItems[items[i].value] = 'true';
                    checked = true;
                
                } else {
                    selectedItems[items[i].value] = ' ';
                    
                }
            }
            
            submessage.classList = "";
            
            getSubscriptionState().then(function(state) {
                 
                if (checked && state.isPushEnabled) {
                    /* Subscribed with newly checked categories, update tags */
                    OneSignal.sendTags(selectedItems).then(function(tagsSent) {
                        // Callback called when tags have finished sending     
                            submessage.classList.add('subupdated');
                    });;
                } else if (!checked && state.isPushEnabled) {
                    /* Subscribed with no categories checked, opt them out */
                    OneSignal.setSubscription(false);
                    submessage.classList.add('unsubscribed');
    
                } else {
                    
                    if (!checked) {
                        /* Unsubscribed with no categories checked, choose category */
                        submessage.classList.add('choosecategory');
                    } else {
                        
                        if (state.isOptedOut) {
                            /* Opted out, opt them back in */
                            OneSignal.setSubscription(true);
    
                        } else {
                            /* Unsubscribed, subscribe them */
                            OneSignal.registerForPushNotifications();
                        }
                        
                        OneSignal.sendTags(selectedItems).then(function(tagsSent) {
                        // Callback called when tags have finished sending     
                            submessage.classList.add('subscribed');
                        });
                        
                    }
                }
                
            });
            event.preventDefault();
        }
    
        function updateManageWebPushSubscriptionButton(buttonSelector) {
            var hideWhenSubscribed = false;
            var subscribeClass = "subscribe";
            var unsubscribeClass = "unsubscribe";
            var subscribeIcon = "fa fa-lg fa-bell";
            var unsubscribeIcon = "fa fa-lg fa-bell-o";
    
            getSubscriptionState().then(function(state) {
                var buttonClass = !state.isPushEnabled || state.isOptedOut ? subscribeClass : unsubscribeClass;
                var buttonIcon = !state.isPushEnabled || state.isOptedOut ? subscribeIcon : unsubscribeIcon;
    
                var element = document.querySelector(buttonSelector);
                if (element === null) {
                    return;
                }
    
                element.removeEventListener('click', onManageWebPushSubscriptionButtonClicked);
                element.addEventListener('click', onManageWebPushSubscriptionButtonClicked);
                element.className = buttonClass;
                document.querySelector("#subscribe-button").children[0].className = buttonIcon;
    
                if (state.hideWhenSubscribed && state.isPushEnabled) {
                    document.querySelector("#subscribe-button").style.display = "none";
                } else {
                    document.querySelector("#subscribe-button").style.display = "";
                }
            });
        }
    
        function getSubscriptionState() {
            return Promise.all([
              OneSignal.isPushNotificationsEnabled(),
              OneSignal.isOptedOut()
            ]).then(function(result) {
                var isPushEnabled = result[0];
                var isOptedOut = result[1];
    
                return {
                    isPushEnabled: isPushEnabled,
                    isOptedOut: isOptedOut
                };
            });
        }
    
        var OneSignal = OneSignal || [];
        var buttonSelector = "#subscribe-submit";
    
        /* This example assumes you've already initialized OneSignal */
        OneSignal.push(function() {
            // If we're on an unsupported browser, do nothing
            if (!OneSignal.isPushNotificationsSupported()) {
                return;
            }
            updateManageWebPushSubscriptionButton(buttonSelector);
            OneSignal.on("subscriptionChange", function(isSubscribed) {
                /* If the user's subscription state changes during the page's session, update the button text */
                updateManageWebPushSubscriptionButton(buttonSelector);
            });
        });

    So what is being done here? when the user clicks the subscribe button, OneSignal is initiated, checked and unchecked checkboxes is being added to an variable object, and sent using OneSignal.sendTags, depending on what the user selects and if the user is subscribed already, the user will also get some feedback when clicking on subscribe.
    If none is checked and the user is subscribed, the user will get opted out.

    I contacted OneSignal to support about deleteTags and they explained that sendTags also removes tags if being sent with an empty value, therefore I don’t use deleteTags to remove tags.

    Hope this helps.
    Best Regards

    Thank you so much, fashioncoree.

    Can’t we get this feature as the plugin only? We should have to request for this feature.

    Agreed, it would be amazing to have category support already baked into the plugin, an alternative would be creating a add-on for the plugin, that we could use until it’s officially released.

    It’s been requested several times, even on their git actually. So hopefully this will be something they will look into in the near future.

    Best Regards

    • This reply was modified 1 year, 4 months ago by  fashioncoree.
Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘Category wise subscription’ is closed to new replies.