diff --git a/gracedb/superevents/utils.py b/gracedb/superevents/utils.py
index 16777701f69413be317acff809c551a55020cda0..ee0f9992e478cc81bee8b0445a4d987972185e6f 100644
--- a/gracedb/superevents/utils.py
+++ b/gracedb/superevents/utils.py
@@ -1,9 +1,16 @@
 from django.shortcuts import get_object_or_404
 
+from .shortcuts import is_superevent
 from .models import Superevent, Log, Labelling
 from events.models import Event, EventLog, Tag
 from events.permission_utils import assign_default_perms
+from events.shortcuts import is_event
 from core.vfile import VersionedFile
+from alerts.superevent_utils import issue_alert_for_superevent_creation, \
+    issue_alert_for_superevent_log, \
+    issue_alert_for_superevent_label_creation, \
+    issue_alert_for_superevent_label_removal
+from alerts.event_utils import issue_alert_for_event_log
 
 import os
 
@@ -39,42 +46,56 @@ def create_superevent(submitter, t_start, t_0, t_end, preferred_event,
     s = Superevent.objects.create(submitter=submitter, t_start=t_start,
         t_0=t_0, t_end=t_end, preferred_event=preferred_event)
 
-    # Write a log message for preferred event
-    new_msg = "Set as preferred event for superevent: {superevent_id}" \
-        .format(superevent_id=s.superevent_id)
-    new_log = create_log(submitter, new_msg, preferred_event,
-        issue_alert=True, autogenerated=False)
-
-    # Add events to superevent
-    # Superevent log message and alerts are taken care of elsewhere, but we
-    # want to record logs and send alerts for the individual events
-    for event in events:
-        add_event_to_superevent(s, event, submitter, add_superevent_log=False,
-            add_event_log=True, issue_superevent_alert=False,
-            issue_event_alert=True)
-
     # Create a log message to record initial superevent parameters
-    # TODO: alert issued for log or not? probably not
     creation_comment = ("Superevent created with t_start={t_start}, t_0={t_0},"
         " t_end={t_end}, preferred_event={preferred_event}").format(
         t_start=t_start, t_0=t_0, t_end=t_end, preferred_event=preferred_event)
-
     if events:
         creation_comment += ", events={events}".format(events=", ".join(
             [ev.graceid() for ev in events]))
-
     # This is autogenerated, but people probably don't want to hide it
     # in the web interface
     superevent_creation_log = create_log(submitter, creation_comment, s,
         issue_alert=False, autogenerated=False)
 
+    # Write a log message for preferred event
+    pref_event_msg = "Set as preferred event for superevent: {superevent_id}" \
+        .format(superevent_id=s.superevent_id)
+    pref_event_log = create_log(submitter, pref_event_msg, preferred_event,
+        issue_alert=False, autogenerated=False)
+
+    # Add events to superevent
+    # Superevent log message and alerts are taken care of elsewhere, but we
+    # want to record logs for the individual events
+    # NOTE: we don't have to worry about a repeat here for the preferred event
+    # since events comes directly from the serializer and hasn't been updated
+    # to include the preferred event (like it would be if we accessed
+    # s.events.all())
+    # Alerts aren't issued here since we want to do that *after* the superevent
+    # creation alert is issued below.
+    event_log_list = []
+    for event in events:
+        _, el = add_event_to_superevent(s, event, submitter,
+            add_superevent_log=False, add_event_log=True,
+            issue_superevent_alert=False, issue_event_alert=False)
+        if el is not None:
+            event_log_list.append(el)
+
+    # Issue all relevant alerts
+    if issue_alert:
+        # Send "new" alert about superevent creation
+        issue_alert_for_superevent_creation(s)
+
+        # "Manually" issue alerts for preferred_event and events
+        issue_alert_for_event_log(pref_event_log)
+
+        for el in event_log_list:
+            issue_alert_for_event_log(el)
+
     # Add labels
-    send_label_alert = False
-    if labels:
-        send_label_alert = True
-        for label in labels:
-            l = add_label_to_superevent(s, label, submitter,
-                add_log_message=True, issue_alert=issue_alert)
+    for label in labels:
+        l = add_label_to_superevent(s, label, submitter,
+            add_log_message=True, issue_alert=issue_alert)
 
     # Create default GroupObjectPermissions - LVC group and executives group
     # can view/change superevents
@@ -84,10 +105,6 @@ def create_superevent(submitter, t_start, t_0, t_end, preferred_event,
     # CREATE DIRECTORY
     os.makedirs(s.datadir)
 
-    # TODO: Send "new" alert about superevent creation
-    if issue_alert:
-        pass
-
     return s
 
 
@@ -110,14 +127,14 @@ def update_superevent(superevent, updater, issue_alert=True, **kwargs):
     superevent.save()
 
     # Write a log message
-    # 'if' statement to handle put requests which don't change entire object
+    # 'if' statement to handle patch requests which don't change entire object
     updates = ["{name}: {old} -> {new}".format(name=k, old=old_params[k],
         new=new_params[k]) for k in new_params.keys()
         if old_params[k] != new_params[k]]
     update_comment = "Updated superevent parameters: {0}".format(
         ", ".join(updates))
     update_log = create_log(updater, update_comment, superevent,
-        issue_alert=False)
+        issue_alert=issue_alert)
 
     # Write event log messages if preferred event changed
     if new_params.has_key('preferred_event') and \
@@ -126,17 +143,13 @@ def update_superevent(superevent, updater, issue_alert=True, **kwargs):
         old_msg = ("Removed as preferred event for superevent: "
             "{superevent_id}").format(superevent_id=superevent.superevent_id)
         old_log = create_log(updater, old_msg, old_params['preferred_event'],
-            issue_alert=True)
+            issue_alert=issue_alert)
 
         # New preferred event
         new_msg = "Set as preferred event for superevent: {superevent_id}" \
             .format(superevent_id=superevent.superevent_id)
         new_log = create_log(updater, new_msg, new_params['preferred_event'],
-            issue_alert=True)
-
-    # TODO: issue alert here? or for log message?
-    if issue_alert:
-        pass
+            issue_alert=issue_alert)
 
     return superevent
 
@@ -154,12 +167,14 @@ def create_log(issuer, comment, event_or_superevent, filename="",
         'comment': comment,
         'filename': filename,
     }
-    if isinstance(event_or_superevent, Superevent):
+    if is_superevent(event_or_superevent):
         log_dict['superevent'] = event_or_superevent
         LogModel = Log
-    elif isinstance(event_or_superevent, Event):
+        alert_func = issue_alert_for_superevent_log
+    elif is_event(event_or_superevent):
         log_dict['event'] = event_or_superevent
         LogModel = EventLog
+        alert_func = issue_alert_for_event_log
     else:
         # TODO: raise error
         logger.error(type(event_or_superevent))
@@ -180,16 +195,12 @@ def create_log(issuer, comment, event_or_superevent, filename="",
         log.file_version = fdest.version
         log.save()
 
-    # TODO: do we issue alert for "auto-generated" log messages?
-    #       or just for the original log message? Dig into the old
-    #       API to find out
+    # Add tags to log messages
     for t in tags:
         add_tag_to_log(log, t, issuer, issue_alert=False)
 
-    # TODO:
-    # Issue an alert for log
     if issue_alert:
-        print('issue alert')
+        alert_func(log)
 
     # TODO:
     # If user is external, add LV-EM tagname to this log message
@@ -213,6 +224,7 @@ def add_tag_to_log(log, tag, user, add_log_message=True, issue_alert=True):
     log.tags.add(tag)
 
     # Create log message to record tag addition?
+    log_for_tag_addition = None
     if add_log_message:
         comment = 'Tagged message {N}: {tag_name}'.format(N=log.N,
             tag_name=tag.name)
@@ -220,6 +232,8 @@ def add_tag_to_log(log, tag, user, add_log_message=True, issue_alert=True):
         log_for_tag_addition = create_log(user, comment, event_or_superevent,
             issue_alert=issue_alert, autogenerated=True)
 
+    return log_for_tag_addition
+
 
 def remove_tag_from_log(log, tag, user, add_log_message=True,
     issue_alert=True):
@@ -228,6 +242,7 @@ def remove_tag_from_log(log, tag, user, add_log_message=True,
     log.tags.remove(tag)
 
     # Create log message to record tag removal?
+    log_for_tag_removal = None
     if add_log_message:
         comment = 'Removed tag {tag_name} from message {N}'.format(
             N=log.N, tag_name=tag.name),
@@ -235,15 +250,21 @@ def remove_tag_from_log(log, tag, user, add_log_message=True,
         log_for_tag_removal = create_log(user, comment, event_or_superevent,
             issue_alert=issue_alert, autogenerated=True)
 
+    return log_for_tag_removal
+
 
 def add_event_to_superevent(superevent, event, user, add_event_log=True,
     add_superevent_log=True, issue_event_alert=True,
     issue_superevent_alert=True):
+    """
+    We return log objects in case they are needed elsewhere
+    """
 
     # Add event to superevent
     superevent.events.add(event)
 
     # Create superevent log message to record event addtion?
+    superevent_log_for_event_addition = None
     if add_superevent_log:
         # Record event addition in superevent logs
         superevent_comment = 'Added event: {graceid}'.format(
@@ -253,6 +274,7 @@ def add_event_to_superevent(superevent, event, user, add_event_log=True,
             autogenerated=True)
 
     # Create event log message to record addition to superevent?
+    event_log_for_addition_to_superevent = None
     if add_event_log:
         # Record addition to superevent in event logs
         event_comment = 'Added to superevent: {superevent_id}'.format(
@@ -260,22 +282,8 @@ def add_event_to_superevent(superevent, event, user, add_event_log=True,
         event_log_for_addition_to_superevent = create_log(user, event_comment,
             event, issue_alert=issue_event_alert, autogenerated=True)
 
-    # TODO: whether this is inside the add_log_message block depends on our
-    #       for the below todo.
-    if issue_superevent_alert:
-        # alerts to superevent channel
-        pass
-
-    if issue_event_alert:
-        # alerts to event channels
-        pass
-
-# TODO: is it enough to just issue alerts about the new log message?
-#       or do we need to issue one specifically with the event being added?
-#       Might need to serialize the event or superevent in some fashion since
-#       we would need to issue the alert from here instead of in create_log.
-#       NOTE: same of course needs to be considered for removing events
-#             from a superevent
+    return superevent_log_for_event_addition, \
+        event_log_for_addition_to_superevent
 
 
 def remove_event_from_superevent(superevent, event, user, add_event_log=True,
@@ -294,6 +302,7 @@ def remove_event_from_superevent(superevent, event, user, add_event_log=True,
     superevent.events.remove(event)
 
     # Create superevent log message to record event removal?
+    superevent_log_for_event_removal = None
     if add_superevent_log:
         # Record event removal in superevent logs
         superevent_comment = 'Removed event: {graceid}'.format(
@@ -302,21 +311,16 @@ def remove_event_from_superevent(superevent, event, user, add_event_log=True,
             superevent, issue_alert=issue_superevent_alert, autogenerated=True)
 
     # Create event log message to record removal from superevent?
+    event_log_for_removal_from_superevent = None
     if add_event_log:
         event_comment ='Removed from superevent: {superevent_id}'.format(
             superevent_id=superevent.superevent_id),
         event_log_for_removal_from_superevent = create_log(user, event_comment,
             event, issue_alert=issue_event_alert, autogenerated=True)
 
-    # TODO: whether this is inside the add_log_message block depends on our
-    #       for the above todo.
-    if issue_superevent_alert:
-        # alerts to superevent channel
-        pass
+    return superevent_log_for_event_removal, \
+        event_log_for_removal_from_superevent
 
-    if issue_event_alert:
-        # alerts to event channels
-        pass
 
 def add_label_to_superevent(superevent, label, user, add_log_message=True,
     issue_alert=True):
@@ -325,38 +329,39 @@ def add_label_to_superevent(superevent, label, user, add_log_message=True,
     labelling = Labelling.objects.create(label=label, creator=user,
         superevent=superevent)
 
+    log_for_label_addition = None
     if add_log_message:
         # Record label addition in superevent logs
         comment = 'Added label: {label_name}'.format(label_name=label.name)
         log_for_label_addition = create_log(user, comment, superevent,
-            issue_alert=issue_alert, autogenerated=True)
+            issue_alert=False, autogenerated=True)
 
-    # TODO: send label alert to superevent channel
     if issue_alert:
-        pass
+        issue_alert_for_superevent_label_creation(labelling)
 
-    return labelling
+    return labelling, log_for_label_addition
 
 
 def remove_label_from_superevent(labelling, user, add_log_message=True,
     issue_alert=True):
 
     # Delete Labelling object
-    label_name = labelling.label.name
     labelling.delete()
 
+    log_for_label_removal = None
     if add_log_message:
         # Record label addition in superevent logs
-        comment = 'Removed label: {label_name}'.format(label_name=label_name)
+        comment = 'Removed label: {label_name}'.format(
+            label_name=labelling.label.name)
         log_for_label_removal = create_log(user, comment, labelling.superevent,
-            issue_alert=issue_alert, autogenerated=True)
+            issue_alert=False, autogenerated=True)
 
-    # TODO: send label alert (or update?) to superevent channel
-    #       if we do this, we probably don't send one for log creation, right?
-    #       (need to check on this)
+    # labelling object still exists in memory, even though it has been
+    # removed from the database and does not have an ID anymore
     if issue_alert:
-        pass
+        issue_alert_for_superevent_label_removal(labelling)
 
+    return log_for_label_removal
 
 def get_or_create_tag(tag_name, display_name=None):
 
@@ -398,17 +403,19 @@ def get_superevent_by_date_id_or_404(request, superevent_id):
     return get_object_or_404(queryset, **filter_kwargs)
 
 
-def confirm_superevent_as_gw(superevent, user):
+def confirm_superevent_as_gw(superevent, user, add_log_message=True,
+    issue_alert=True):
 
     # Update superevent (mark as a GW, construct new ID, etc.)
     superevent.confirm_as_gw()
 
     # Create log message
-    message = "Confirmed as a gravitational wave."
-    gw_log = create_log(user, message, superevent, issue_alert=True,
-        autogenerated=False)
+    gw_log = None
+    if add_log_message:
+        message = "Confirmed as a gravitational wave."
+        gw_log = create_log(user, message, superevent, issue_alert=issue_alert,
+            autogenerated=False)
 
     # TODO: add label?
 
-    # TODO:
-    # issue alert
+    return gw_log