diff --git a/gracedb/admin.py b/gracedb/admin.py
index 9b668ac02e7534a3d7bfedc1dc4c23c11cf459e0..8dc1cbb24235ec7166527b791a99b294bea18455 100644
--- a/gracedb/admin.py
+++ b/gracedb/admin.py
@@ -1,5 +1,6 @@
 #from gracedb.gracedb.models import Analysis, Group, User
 from models import Event, EventLog, User, Group
+from models import Label, Labelling
 from django.contrib import admin
 
 #class AnalysisAdmin(admin.ModelAdmin):
@@ -10,4 +11,6 @@ admin.site.register(Event)
 admin.site.register(EventLog)
 admin.site.register(User)
 admin.site.register(Group)
+admin.site.register(Label)
+admin.site.register(Labelling)
 
diff --git a/gracedb/models.py b/gracedb/models.py
index acd19e4e42e7e14e6deb317fc8ab22ad20f6ff7a..6451c012f74aad99fdf076a2c04343177f6d777e 100644
--- a/gracedb/models.py
+++ b/gracedb/models.py
@@ -30,6 +30,12 @@ class Group(models.Model):
     def __unicode__(self):
         return self.name
 
+class Label(models.Model):
+    name = models.CharField(max_length=20)
+    # XXX really, does this belong here? probably not.
+    defaultColor = models.CharField(max_length=20, default="black")
+    def __unicode__(self):
+        return self.name
 
 class Event(models.Model):
     ANALYSIS_TYPE_CHOICES = (
@@ -64,6 +70,8 @@ class Event(models.Model):
     # old date encoded uids.
     uid = models.CharField(max_length=20, unique=False, default="")
 
+    labels = models.ManyToManyField(Label, through="Labelling")
+
     tags = TagField()
 
     def get_tags(self):
@@ -119,6 +127,12 @@ class EventLog(models.Model):
         else:
             return None
 
+class Labelling(models.Model):
+    event = models.ForeignKey(Event)
+    label = models.ForeignKey(Label)
+    creator = models.ForeignKey(User)
+    created = models.DateTimeField(auto_now_add=True)
+
 class Approval(models.Model):
     COLLABORATION_CHOICES = ( ('L','LIGO'), ('V','Virgo'), )
     approver = models.ForeignKey(User)
diff --git a/gracedb/views.py b/gracedb/views.py
index 626e8921e7c2ee1befdbdbe46c8c15d8d93c7701..04ea0035e59956f94ef65abf1d34281ce4fb274c 100644
--- a/gracedb/views.py
+++ b/gracedb/views.py
@@ -8,7 +8,7 @@ from django.contrib.sites.models import Site
 
 from django.views.generic.list_detail import object_detail, object_list
 
-from models import Event, Group, EventLog
+from models import Event, Group, EventLog, Labelling, Label
 from forms import CreateEventForm, EventSearchForm
 from alert import issueAlert
 from translator import handle_uploaded_data
@@ -257,6 +257,32 @@ def cli_tag(request):
 
     return response
 
+def cli_label(request):
+    graceid = request.POST.get('graceid')
+    labelName = request.POST.get('label')
+
+    event = graceid and Event.getByGraceid(graceid)
+    
+    try:
+        label = Label.objects.filter(name=labelName)[0]
+    except IndexError:
+        raise ValueError("No such Label '%s'" % labelName)
+
+    # Don't add a label more than once.
+    if label not in event.labels.all():
+        labelling = Labelling(
+                event = event,
+                label = label,
+                creator = request.ligouser
+            )
+        labelling.save()
+
+    msg = str({})
+    response = HttpResponse(mimetype='application/json')
+    response.write(msg)
+    response['Content-length'] = len(msg)
+
+    return response
 
 def log(request):
     message = request.POST.get('message')
diff --git a/templates/gracedb/event_detail.html b/templates/gracedb/event_detail.html
index ae69f7250f173f758ff13709e6cede59124d8114..5650a8cb5a0d08742aa4dd5cf1f5d3501683c42c 100644
--- a/templates/gracedb/event_detail.html
+++ b/templates/gracedb/event_detail.html
@@ -26,11 +26,12 @@
   <tr><th>Sumitter</th><td>{{ object.submitter.name }}</td></tr>
   <tr><th>Created{{ "created"|timeselect:"utc" }}</th><td>{{ object.created|multiTime:"created" }}
                           </td></tr>
-  <tr><th>Tags</th><td>
-     {% for tag in object.get_tags %}
-        {{ tag.name }}
+  <tr><th>Labels</th><td>
+     {% for labelling in object.labelling_set.all %}
+        <span title="{{labelling.creator.name}}  {{labelling.created|utc}}" style="color: {{labelling.label.defaultColor}}">{{ labelling.label.name }}</span>
      {% endfor %}
      </td></tr>
+
 </table>
 
 {% if object.eventlog_set.count %}
diff --git a/urls.py b/urls.py
index 6c9be2ed05079020591f33e7a83126f7b1a37e81..2cdb02cbd70edc49361071fde1f2c1aba93d74fd 100644
--- a/urls.py
+++ b/urls.py
@@ -19,6 +19,7 @@ urlpatterns = patterns('',
     (r'^cli/log', 'gracedb.gracedb.views.log'),
     (r'^cli/upload', 'gracedb.gracedb.views.upload'),
     (r'^cli/tag', 'gracedb.gracedb.views.cli_tag'),
+    (r'^cli/label', 'gracedb.gracedb.views.cli_label'),
     #(r'^cli/ping/(?P<arg>.*)', 'gracedb.gracedb.views.ping'),
     (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', 
         {'feed_dict': feeds}),