Modify destination before URL redirect

Hello Mailwizz users & Twisted,

how are you?

I am trying to create an extension to add Google UTM tags automatically to links based on customer groups settings. I know adding UTM tags is not a big deal right now, but such URLs are not sanitized and I need more flexibility and want it done automatically when it is set up.

I found that this is the action closest to what I need done:

Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url, $destination);

The ideal scenario would be take $destination, make the needed modifications and redirect. Yet under such action is where the subscribers open tracking occurs, so doing such redirect when the action occur with end up meaning that I would not be capable of tracking opens.

I believe that moving such hook bellow the snippet in this way might solve my issue:

/apps/frontend/controllers/CampaignsController.php
PHP:
         //WHERE HOOK ORIGINALLY WAS
        // since 1.3.5.9
        if ($campaign->option->open_tracking == CampaignOption::TEXT_YES && !$subscriber->hasOpenedCampaign($campaign)) {
            $track = new CampaignTrackOpen();
            $track->campaign_id   = $campaign->campaign_id;
            $track->subscriber_id = $subscriber->subscriber_id;
            $track->ip_address    = Yii::app()->request->getUserHostAddress();
            $track->user_agent    = substr(Yii::app()->request->getUserAgent(), 0, 255);
            if ($track->save(false)) {
                try {
                    Yii::app()->hooks->doAction('frontend_campaigns_after_track_opening', $this, $track, $campaign, $subscriber);
                } catch (Exception $e) {}
            }
        }
        // MOVED HOOK
        Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url, $destination);   
        $this->redirect($destination, true, 301);
Yet I am not very fond of modifying the core and that is why I am posting here. Is there any other way around this?

Maybe adding a filter to make me capable of modifying $destination via an extension would be a nice solution.

What do you think?

Thanks!
 
Ok...

I solved my problem by just copying the snippet from the core to my extension before it redirects.

I hope this does not cause any issues. If anyone has any other approach to recommend I am all ears (eyes).

Cheers!
 

twisted1919

Administrator
Staff member
@Ignacioport -
It is safe to add
PHP:
$destination = Yii::app()->hooks->applyFilters('frontend_campaigns_track_url_destination', $destination, $this, $campaign, $subscriber, $url);
right before:
PHP:
Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url, $destination);
So we have:
PHP:
        $destination = str_replace('&', '&', $url->destination);
        if (preg_match('/\[(.*)?\]/', $destination)) {
            list(,,$destination) = CampaignHelper::parseContent($destination, $campaign, $subscriber, false);
        }

        $destination = Yii::app()->hooks->applyFilters('frontend_campaigns_track_url_destination', $destination, $this, $campaign, $subscriber, $url);

        Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url, $destination);

        // since 1.3.5.9
        if ($campaign->option->open_tracking == CampaignOption::TEXT_YES && !$subscriber->hasOpenedCampaign($campaign)) {
            $track = new CampaignTrackOpen();
            $track->campaign_id   = $campaign->campaign_id;
            $track->subscriber_id = $subscriber->subscriber_id;
            $track->ip_address    = Yii::app()->request->getUserHostAddress();
            $track->user_agent    = substr(Yii::app()->request->getUserAgent(), 0, 255);
            if ($track->save(false)) {
                try {
                    Yii::app()->hooks->doAction('frontend_campaigns_after_track_opening', $this, $track, $campaign, $subscriber);
                } catch (Exception $e) {}
            }
        }
        //

        $this->redirect($destination, true, 301);
This way you can hook into "frontend_campaigns_track_url_destination" from any extension.
You can add this code to core since will be added by me anyway.
 

twisted1919

Administrator
Staff member
Actually, if i think better, moving the action hook a bit to the top makes more sense, so this is the final thing:
PHP:
        $track = new CampaignTrackUrl();
        $track->url_id          = $url->url_id;
        $track->subscriber_id   = $subscriber->subscriber_id;
        $track->ip_address      = Yii::app()->request->getUserHostAddress();
        $track->user_agent      = substr(Yii::app()->request->getUserAgent(), 0, 255);

        if ($track->save(false)) {
            // hook added in 1.2
            $this->setData('ipLocationSaved', false);
            try {
                Yii::app()->hooks->doAction('frontend_campaigns_after_track_url', $this, $track, $campaign, $subscriber);
            } catch (Exception $e) {

            }
        }

        // start change
        $url->destination = str_replace('&', '&', $url->destination);
        Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url);

        $destination = $url->destination;
        if (preg_match('/\[(.*)?\]/', $destination)) {
            list(,,$destination) = CampaignHelper::parseContent($destination, $campaign, $subscriber, false);
        }
       // end change

        // since 1.3.5.9
        if ($campaign->option->open_tracking == CampaignOption::TEXT_YES && !$subscriber->hasOpenedCampaign($campaign)) {
            $track = new CampaignTrackOpen();
            $track->campaign_id   = $campaign->campaign_id;
            $track->subscriber_id = $subscriber->subscriber_id;
            $track->ip_address    = Yii::app()->request->getUserHostAddress();
            $track->user_agent    = substr(Yii::app()->request->getUserAgent(), 0, 255);
            if ($track->save(false)) {
                try {
                    Yii::app()->hooks->doAction('frontend_campaigns_after_track_opening', $this, $track, $campaign, $subscriber);
                } catch (Exception $e) {}
            }
        }
        //

        $this->redirect($destination, true, 301);
So in your action, you can safely modify $url->destination as you wish.
 
Thanks!

The second solution works like a charm, and it even allows me to easily use custom tags in my new links :)

So yeah, it makes more sense. Do you plan to add such change in the next update?

I have another issue for you. To make my extension work i need to get the group_id of the customer which is sending the campaign.

According to the campaign model $campaign has the group_id attribute

yet if I did $campaign->group_id or $campaign->group->group_id I ended up with null. This after hooking to the aforementioned hook:

PHP:
Yii::app()->hooks->doAction('frontend_campaigns_after_track_url_before_redirect', $this, $campaign, $subscriber, $url);
Why is it so? Is there something wrong in what I am doing?

I ended up using $campaign->customer_id to load a customer class and fetch the group_id via that class. But looking at the campaign model I thought this was not necessary.

Cheers and thanks for all your support!
 

twisted1919

Administrator
Staff member
@Ignacioport - The above change is already added so all releases will have it, no need to worry about updates ;)
Related to customer group, when you do $campaign->group->group_id you actually try to load the campaign group, not the customer group.
So instead, what you need is: $campaign->customer->group_id ;)
 
Top