diff --git a/opentech/apply/users/models.py b/opentech/apply/users/models.py
index 38c52a7239a5eb8cf6dac274484634f2fa9fe9a2..f6a958cc9312bdc6de152e38c8cd0fe108c02681 100644
--- a/opentech/apply/users/models.py
+++ b/opentech/apply/users/models.py
@@ -1,6 +1,7 @@
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.models import AbstractUser, BaseUserManager
+from django.urls import reverse
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
 
@@ -86,6 +87,9 @@ class User(AbstractUser):
 
     objects = UserManager()
 
+    def get_absolute_url(self):
+        return reverse('wagtailusers_users:edit', args=(self.id,))
+
     def __str__(self):
         return self.get_full_name() if self.get_full_name() else self.get_short_name()
 
diff --git a/opentech/apply/users/wagtail_hooks.py b/opentech/apply/users/wagtail_hooks.py
index 87ef900f51ba9bfe9c9a84bdceed54c413cdad96..dcd5276f5f356dea951f5dfba794fb96dda19954 100644
--- a/opentech/apply/users/wagtail_hooks.py
+++ b/opentech/apply/users/wagtail_hooks.py
@@ -2,6 +2,8 @@ from django.conf.urls import url
 
 from wagtail.core import hooks
 
+from opentech.apply.utils.notifications import slack_notify
+
 from .admin_views import index
 
 
@@ -10,3 +12,24 @@ def register_admin_urls():
     return [
         url(r'^users/$', index, name='index'),
     ]
+
+
+@hooks.register('after_create_user')
+def notify_after_create_user(request, user):
+    slack_notify(
+        message=f'{request.user} has crated a new account for {user}.',
+        request=request,
+        related=user,
+    )
+
+
+@hooks.register('after_edit_user')
+def notify_after_edit_user(request, user):
+    roles = list(user.groups.values_list('name', flat=True))
+    if roles:
+        roles = ', '.join(roles)
+        slack_notify(
+            message=f'{request.user} has edited the account for {user} that now have these roles: {roles}.',
+            request=request,
+            related=user,
+        )
diff --git a/opentech/apply/utils/notifications.py b/opentech/apply/utils/notifications.py
new file mode 100644
index 0000000000000000000000000000000000000000..bed3683da90108043926563a59f6c05e7d8f3178
--- /dev/null
+++ b/opentech/apply/utils/notifications.py
@@ -0,0 +1,57 @@
+import requests
+
+from django.conf import settings
+
+
+class SlackNotifications():
+
+    def __init__(self):
+        self.destination = settings.SLACK_DESTINATION_URL
+        self.target_room = settings.SLACK_DESTINATION_ROOM
+
+    def __call__(self, *args, recipients=None, related=None, **kwargs):
+        return self.send_message(*args, recipients=None, related=related, **kwargs)
+
+    def slack_users(self, users):
+        slack_users = []
+        for user in users:
+            if user.slack:
+                slack_users.append(f'<{user.slack}>')
+        return ' '.join(slack_users)
+
+    def slack_link(self, request, related):
+        slack_link = ''
+        try:
+            link = request.scheme + '://' + request.get_host() + related.get_absolute_url()
+        except AttributeError:
+            pass
+        else:
+            title = str(related)
+            slack_link = f'<{link}|{title}>'
+        return slack_link
+
+    def send_message(self, message, request, recipients=None, related=None, **kwargs):
+        if not self.destination or not self.target_room:
+            errors = list()
+            if not self.destination:
+                errors.append('Destination URL')
+            if not self.target_room:
+                errors.append('Room ID')
+            return 'Missing configuration: {}'.format(', '.join(errors))
+
+        slack_users = self.slack_users(recipients) if recipients else ''
+
+        slack_link = self.slack_link(request, related) if related else ''
+
+        message = ' '.join([slack_users, message, slack_link]).strip()
+
+        data = {
+            "room": self.target_room,
+            "message": message,
+        }
+        response = requests.post(self.destination, json=data)
+
+        return str(response.status_code) + ': ' + response.content.decode()
+
+
+slack_notify = SlackNotifications()