I have a custom plugin that logs into a database each time someone downloads an image. This is achieved through a module installed with my mod files etc.

The plugin records the current logged-in user who clicks to download, the image they downloaded, and the time/date etc.

Currently I generate a text-based email that says to the image owner 'Someone from company-a has downloaded the image titled x at 10 am'. It's basic and texty but it does work.

Ideally, it would be nice to tie this into Postmaster, but I think it requires a custom hook to do so, possibly installed into postmaster. My question is, how do I call my custom hook from within my module and push information to it so I can use the variables in Postmaster?

My tag is currently

{exp:download:log_download image="45"}

, which pushes in the image info, the other stuff comes from DB lookups from the owner of said image and also the current member info from sessions.

I would love to create a parcel in postmaster and pull in the variables and have a nice branded html email as described above.

I am on ee 2.5.3 and postmaster 1.2. Any points in the right direction would be helpful. I have created modules and plugins for client use, but not used any hooks as of yet and need to get my head wrapped around it.

2 Answers 2


Hooks are rather abstract and require you to have a working plugin/module with your own hooks setup. So before you go any further I would be sure you have a good grasp on how to use the most basic forms of hooks. It might be wise to even write a simple extension just to go through the process.

Postmaster extends ExpressionEngine's native handling of hooks. So when you install a hook via Postmaster, you a really installing specialized extension. So knowing that building Postmaster hooks is similar to extensions, this might be worth a read before you get started. http://ellislab.com/expressionengine/user-guide/development/extensions.html

Note, the process varies and end results vary dramatically from regular extensions, but the logical is very similar.

Step 1 - Create a hook

Create a hook in your plugin. It can pass any data to the hook, just know that any data you pass to the hook can be used within the Postmaster template. Below is a sample hook from my Google Maps for EE add-on. It simply allows devs to alter the POST data each time it is retrieved. In this case, call this hook would pass all the $_POST vars to the Postmaster hook.

/* -------------------------------------------
/* 'gmap_post' hook.
/*  - Modify post variables before method executes
/*  - Added v3.0 */

    $edata = $this->EE->extensions->call('gmap_post', $_POST);          

    if($edata !== NULL) $_POST = $edata;

    if ($this->EE->extensions->end_script === TRUE) return;
/* -------------------------------------------*/

Step 2. Extend Postmaster's Base_hook class

Once you have your hook installed in your plugin to do pass whatever data you want, you will want to reference the Base_hook class in Postmaster. https://objectivehtml.com/postmaster/api/hooks

Base_hook allows you to extend the default functionality and inherit all the tools I have provided to make it easy for devs to build these hook. You really only need one method, and that is the trigger() method.

class Gmap_post_postmaster_hook extends Base_hook {

protected $title = 'Gmap Post';

public function __construct()

public function trigger($_POST)
    // Your trigger logic

    $vars = array_merge($_POST, array(
        'var_1' => 'Some Value 1',
        'var_2' => 'Some Value 2',
        'var_3' => 'Some Value 3'

    return parent::send($vars);

It's important to note that parameter passed to the trigger() method are the same as those that you passed in your hook. So in my example, I passed one parameters, the $_POST array. You could pass as many variables as you want, and they will get passed to the trigger method in the same fashion.

Once you have created your hook's class, save it in the system/expressionengine/third_party/postmaster/hooks directory.

Step 3 - Install Hook

Once you have create your hook and have it saved, it will appear in the hooks dropdown menu within the Postmater CP. Simply select your hook from the list and create a template. Postmaster will parse all the variables you pass to the template.

Method Reference

All the method in the classes are documented in full detail in the API docs. There are A TON of underlying features and capabilities. Pretty much anything is possible. https://objectivehtml.com/postmaster/api/hooks

  • So to be clear, I create a custom hook file in Postmaster, then from within my mod file, I push information to it? Do I need to create my own extension file in my module to do this or can I simply call the hook from witihn my mod method?
    – Aaron
    Commented Dec 20, 2012 at 12:38
  • 1
    There is no need to create an extension file. Postmaster manages installed/editing/deleting the extension itself. It's actually create an extension in the exp_extensions table, but it's different from native ext's. Extending the Postmaster API and create your own class is really all you need. If anyone has any more questions just make a new thread, or email [email protected]. Commented Dec 23, 2012 at 8:05

I worked through this with Justin and wanted to post this so others can use it.

Basically I have a mod file with a custom function that logs when an image is downloaded. My variables are all logged after being set up. Here's the variables:

$my_download = array();

    $my_download["size"] = $image_size;
    $my_download["entry_id"] = $entry_id;
    $my_download["image_file"] =  $image_file;
    $my_download["encoded_image_file"] = '<img src="data:image/jpeg;base64,' . base64_encode( $image_file ) . '" width="70" />';
    $my_download["image_path"] = 'images/brands/'.$row['entry_id'].'/'.$row['title'].'__smallest.jpg';
    $my_download["image_title"] = $image_title;
    $my_download["member_id"] = $member_id;
    $my_download["company"] = $company;
    $my_download["country_code"] = $country_code;

And then in that method I create a hook and push it to postmaster:

// -------------------------------------------
    // 'member_download_image_postmaster' hook.
    //  - Send Postmaster email after download has been recorded
        if ($this->EE->extensions->active_hook('member_download_image') === TRUE)
            $edata = $this->EE->extensions->call('member_download_image', $my_download);          

            if($edata !== NULL) $my_download = $edata;

            if ($this->EE->extensions->end_script === TRUE) return;
    // -------------------------------------------

From that, I created a simple custom hook from within the postmaster /third_party/postmaster/hooks/ folder:

class Member_download_image_postmaster_hook extends Base_hook {

protected $title = 'Member Download Image';

public function __construct() {
public function trigger($my_download) {

Then from within postmaster itself, I created a new hook instead of a parcel, v1.2 Postmaster at this point:

 <h2>Image Download</h2>
  <p> A user at Domain.com from: {hook:company} downloaded your image titled: {hook:image_title}, on {current_time format="%d/%m/%Y"}</p>
  <p>Image: <img src="http://domain.com/{hook:image_path}" /></p>

Each time someone downloads my image, it logs it to the DB and fires off a tasty html styled email. The {hook:var} tag is used instead of {parcel:var} as it is a hook and not a parcel, funnily enough.

Thanks a ton to Justin for this and I can't recommend Postmaster enough if you are doing this sort of thing.

  • Nice writeup, I am just sure people will find the combination of my post and yours very helpful. Glad you got it working. Commented Dec 20, 2012 at 16:04
  • Both of your answers are super helpful. Thanks! Commented Dec 21, 2012 at 2:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.