<p>Here's a simplified version of how I'm doing that in a custom module.</p>
<p>You can create a Twig template at <code>emails/customer-details-updated</code> and it'll receive a <code>user</code> variable from this code with all the user's fields. At the time I couldn't find an easy way to find exactly which fields had been updated other than querying for the user data and looping through every field to compare the post data, which seemed like a lot of effort... but let me know if you manage to do that!</p>
<pre class="lang-php prettyprint-override"><code>
&lt;?php

use craft\services\Elements;
use craft\mail\Message;
use craft\web\View;
use yii\base\Event;
use yii\base\Module;

class Site extends Module
{
    public function init()
    {
        // --------------------------------------------
        // NOTIFY ADMIN WHEN A USER UPDATES THEIR DETAILS
        // or if they are updated in the CP.
        // --------------------------------------------

        Event::on(
            Elements::class,
            Elements::EVENT_BEFORE_SAVE_ELEMENT,
            function (Event $e) {
                
                // bail out if it's not a User being saved
                if (!$e-&gt;element instanceof \craft\elements\User) { return; }

                // set variables for consumption by the template
                $templateVars = ['user' =&gt; $e-&gt;element];

                // if it's a CP request, we'll need to switch the template mode to 'TEMPLATE_MODE_SITE'
                // in order to access the site templates for rendering the email body
                $oldMode = Craft::$app-&gt;view-&gt;getTemplateMode();
                Craft::$app-&gt;view-&gt;setTemplateMode(View::TEMPLATE_MODE_SITE);

                // build the email body using a site template now that we're in the right template mode...
                $htmlBody = Craft::$app-&gt;view-&gt;renderTemplate('emails/customer-details-updated', $templateVars);

                // ...then put it back again.
                Craft::$app-&gt;view-&gt;setTemplateMode($oldMode);

                // assemble and send...
                $message = (new Message())
                    -&gt;setSubject('Alert: A customer updated their profile')
                    -&gt;setHtmlBody($htmlBody)
                    -&gt;setTo('someone@example.com');

                Craft::$app-&gt;getMailer()-&gt;send($message);
            }
        );
    }
}
</code></pre>
<p>Edit to add: if you want to ensure that the email only triggers from front-end edits, and not from edits made in the Craft control panel, add an early return statement based on the request's <code>isCpRequest</code> property (<code>Craft::$app-&gt;request-&gt;isCpRequest</code>) e.g.</p>
<pre class="lang-php prettyprint-override"><code>if (Craft::$app-&gt;request-&gt;isCpRequest) { return; }
</code></pre>

CC BY-SA 4.0
2022-02-11T16:14:37.297Z
^ Great answer! Minor simplification: since Craft 3.4.0 it's not necessary anymore to switch the template mode around with `setTemplateMode()` and `getTemplateMode()`. Instead, you can simply pass the desired template mode as the third parameter to the `renderTemplate()` method: `Craft::$app->view->renderTemplate('emails/customer-details-updated', $templateVars, View::TEMPLATE_MODE_SITE);`.
Mats Mikkel Rummelhoff
CC BY-SA 4.0
2022-02-11T17:25:38.100Z
oooh cool thanks, that always seemed like a messy inconvenience.
James Smith
CC BY-SA 4.0
2022-02-11T17:56:25.600Z
Thank you James. Sorry I have never done something like that. What should I do with this code? Create a module.php file? I tried to use the documentations on craft but it doesn't seem to work...
LessMore Creative Studio
CC BY-SA 4.0
2022-02-14T09:08:52.053Z
Instructions for creating/configuring a custom module are listed here: https://craftcms.com/docs/3.x/extend/module-guide.html#update-the-application-config - can you be more specific about what doesn't work?
James Smith
CC BY-SA 4.0
2022-02-11T15:41:18.843Z
2022-02-14T09:12:57.673Z
2022-02-14T09:12:57.673Z
James Smith
<p>I have a client that wants to be notified by email whenever any user on the site updates their profile fields. Right now, users can update their profiles through a front end form.</p>
<p>Ideally, after any update, an email will be sent to the content admin of the site (not main admin user but another user group).
I assume that a plugin will be needed but I have zero clue where and how to start.
Any help would be highly appreciated.</p>

CC BY-SA 4.0
2022-02-11T15:31:16.817Z
Do you also want to send the notification if an admin updates someone's profile from the Craft control panel?
James Smith
CC BY-SA 4.0
2022-02-11T17:56:47.730Z
I am trying to only send the notification when the user is being updated via the front end form
LessMore Creative Studio
<users><plugin-pushnotifications>
Admin notification when user updates user profile
# Admin notification when user updates user profile

(Asked by: username_0 on 2022-02-11)

I have a client that wants to be notified by email whenever any user on the site updates their profile fields. Right now, users can update their profiles through a front end form.

Ideally, after any update, an email will be sent to the content admin of the site (not main admin user but another user group).
I assume that a plugin will be needed but I have zero clue where and how to start.
Any help would be highly appreciated.

**Tags:** users, plugin-pushnotifications

> **Comments:**
> **username_1**: Do you also want to send the notification if an admin updates someone's profile from the Craft control panel?  
> **username_0**: I am trying to only send the notification when the user is being updated via the front end form  

---

## 1 answers

### Answer by username_1 on 2022-02-11. Score: 2

Here's a simplified version of how I'm doing that in a custom module.
You can create a Twig template at emails/customer-details-updated and it'll receive a user variable from this code with all the user's fields. At the time I couldn't find an easy way to find exactly which fields had been updated other than querying for the user data and looping through every field to compare the post data, which seemed like a lot of effort... but let me know if you manage to do that!

element instanceof \craft\elements\User) { return; }

                // set variables for consumption by the template
                $templateVars = ['user' => $e->element];

                // if it's a CP request, we'll need to switch the template mode to 'TEMPLATE_MODE_SITE'
                // in order to access the site templates for rendering the email body
                $oldMode = Craft::$app->view->getTemplateMode();
                Craft::$app->view->setTemplateMode(View::TEMPLATE_MODE_SITE);

                // build the email body using a site template now that we're in the right template mode...
                $htmlBody = Craft::$app->view->renderTemplate('emails/customer-details-updated', $templateVars);

                // ...then put it back again.
                Craft::$app->view->setTemplateMode($oldMode);

                // assemble and send...
                $message = (new Message())
                    ->setSubject('Alert: A customer updated their profile')
                    ->setHtmlBody($htmlBody)
                    ->setTo('someone@example.com');

                Craft::$app->getMailer()->send($message);
            }
        );
    }
}

Edit to add: if you want to ensure that the email only triggers from front-end edits, and not from edits made in the Craft control panel, add an early return statement based on the request's isCpRequest property (Craft::$app->request->isCpRequest) e.g.
if (Craft::$app->request->isCpRequest) { return; }

> **Comments:**
> **username_2**: ^ Great answer! Minor simplification: since Craft 3.4.0 it's not necessary anymore to switch the template mode around with `setTemplateMode()` and `getTemplateMode()`. Instead, you can simply pass the desired template mode as the third parameter to the `renderTemplate()` method: `Craft::$app->view->renderTemplate('emails/customer-details-updated', $templateVars, View::TEMPLATE_MODE_SITE);`.  
> **username_1**: oooh cool thanks, that always seemed like a messy inconvenience.  
> **username_0**: Thank you James. Sorry I have never done something like that. What should I do with this code? Create a module.php file? I tried to use the documentations on craft but it doesn't seem to work...  
> **username_1**: Instructions for creating/configuring a custom module are listed here: https://craftcms.com/docs/3.x/extend/module-guide.html#update-the-application-config - can you be more specific about what doesn't work?  

---

