diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 All notable changes to the LaunchDarkly Haskell Server-side SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).
 
+## [2.1.0] - 2021-02-04
+### Added:
+- Added the `alias` function. This can be used to associate two user objects for analytics purposes by generating an alias event.
+
 ## [2.0.2] - 2020-10-13
 ### Fixed:
 - Removed unused legacy &#34;sel&#34; field from flag model.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -39,4 +39,3 @@
     * [docs.launchdarkly.com](https://docs.launchdarkly.com/  "LaunchDarkly Documentation") for our documentation and SDK reference guides
     * [apidocs.launchdarkly.com](https://apidocs.launchdarkly.com/  "LaunchDarkly API Documentation") for our API documentation
     * [blog.launchdarkly.com](https://blog.launchdarkly.com/  "LaunchDarkly Blog Documentation") for the latest product updates
-    * [Feature Flagging Guide](https://github.com/launchdarkly/featureflags/  "Feature Flagging Guide") for best practices and strategies
diff --git a/launchdarkly-server-sdk.cabal b/launchdarkly-server-sdk.cabal
--- a/launchdarkly-server-sdk.cabal
+++ b/launchdarkly-server-sdk.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 82a2c20d4d75771f517f54ceb64f5fc0543b4e2c6cc3d45c378a7e00d0b817e9
+-- hash: 3d67aab3aa6aedf0c1a1f7e272f48d33110b90dc4237a50793cb8ce5885b4bbc
 
 name:           launchdarkly-server-sdk
-version:        2.0.2
+version:        2.1.0
 synopsis:       Server-side SDK for integrating with LaunchDarkly
 description:    Please see the README on GitHub at <https://github.com/launchdarkly/haskell-server-sdk#readme>
 category:       Web
diff --git a/src/LaunchDarkly/Server.hs b/src/LaunchDarkly/Server.hs
--- a/src/LaunchDarkly/Server.hs
+++ b/src/LaunchDarkly/Server.hs
@@ -57,6 +57,7 @@
     , flushEvents
     , identify
     , track
+    , alias
     , Status(..)
     , getStatus
     ) where
diff --git a/src/LaunchDarkly/Server/Client.hs b/src/LaunchDarkly/Server/Client.hs
--- a/src/LaunchDarkly/Server/Client.hs
+++ b/src/LaunchDarkly/Server/Client.hs
@@ -22,6 +22,7 @@
     , flushEvents
     , identify
     , track
+    , alias
     , Status(..)
     , getStatus
     ) where
@@ -46,7 +47,7 @@
 import           LaunchDarkly.Server.Client.Internal
 import           LaunchDarkly.Server.User.Internal     (User(..), userSerializeRedacted)
 import           LaunchDarkly.Server.Details           (EvaluationDetail(..), EvaluationReason(..), EvalErrorKind(..))
-import           LaunchDarkly.Server.Events            (IdentifyEvent(..), CustomEvent(..), EventType(..), makeBaseEvent, queueEvent, makeEventState, addUserToEvent)
+import           LaunchDarkly.Server.Events            (IdentifyEvent(..), CustomEvent(..), AliasEvent(..), EventType(..), makeBaseEvent, queueEvent, makeEventState, addUserToEvent, userGetContextKind)
 import           LaunchDarkly.Server.Network.Eventing  (eventThread)
 import           LaunchDarkly.Server.Network.Streaming (streamingThread)
 import           LaunchDarkly.Server.Network.Polling   (pollingThread)
@@ -118,8 +119,28 @@
 track :: Client -> User -> Text -> Maybe Value -> Maybe Double -> IO ()
 track (Client client) (User user) key value metric = do
     x <- makeBaseEvent $ addUserToEvent (getField @"config" client) user CustomEvent
-        { key = key, user = Nothing, userKey = Nothing, metricValue = metric, value = value }
+        { key         = key
+        , user        = Nothing
+        , userKey     = Nothing
+        , metricValue = metric
+        , value       = value
+        , contextKind = userGetContextKind user
+        }
     queueEvent (getField @"config" client) (getField @"events" client) (EventTypeCustom x)
+
+-- | Alias associates two users for analytics purposes with an alias event.
+--
+-- The first parameter should be the new version of the user,
+-- the second parameter should be the old version.
+alias :: Client -> User -> User -> IO ()
+alias (Client client) (User currentUser) (User previousUser) = do
+    x <- makeBaseEvent $ AliasEvent
+        { key                 = getField @"key" currentUser
+        , contextKind         = userGetContextKind currentUser
+        , previousKey         = getField @"key" previousUser
+        , previousContextKind = userGetContextKind previousUser
+        }
+    queueEvent (getField @"config" client) (getField @"events" client) (EventTypeAlias x)
 
 -- | Flush tells the client that all pending analytics events (if any) should be
 -- delivered as soon as possible. Flushing is asynchronous, so this method will
diff --git a/src/LaunchDarkly/Server/Client/Internal.hs b/src/LaunchDarkly/Server/Client/Internal.hs
--- a/src/LaunchDarkly/Server/Client/Internal.hs
+++ b/src/LaunchDarkly/Server/Client/Internal.hs
@@ -25,7 +25,7 @@
 
 -- | The version string for this library.
 clientVersion :: Text
-clientVersion = "2.0.2"
+clientVersion = "2.1.0"
 
 -- | The status of the client initialization.
 data Status
diff --git a/src/LaunchDarkly/Server/Events.hs b/src/LaunchDarkly/Server/Events.hs
--- a/src/LaunchDarkly/Server/Events.hs
+++ b/src/LaunchDarkly/Server/Events.hs
@@ -21,6 +21,18 @@
 import           LaunchDarkly.Server.Details         (EvaluationReason(..))
 import           LaunchDarkly.Server.Features        (Flag)
 
+data ContextKind = ContextKindUser | ContextKindAnonymousUser
+    deriving (Eq, Show)
+
+instance ToJSON ContextKind where
+  toJSON contextKind = String $ case contextKind of
+      ContextKindUser          -> "user" 
+      ContextKindAnonymousUser -> "anonymousUser"
+
+userGetContextKind :: UserI -> ContextKind
+userGetContextKind user = if (getField @"anonymous" user)
+    then ContextKindAnonymousUser else ContextKindUser
+
 data EvalEvent = EvalEvent
     { key                  :: !Text
     , variation            :: !(Maybe Natural)
@@ -128,18 +140,21 @@
     , version      :: !(Maybe Natural)
     , variation    :: !(Maybe Natural)
     , reason       :: !(Maybe EvaluationReason)
+    , contextKind  :: !ContextKind
     } deriving (Generic, Show)
 
 instance ToJSON FeatureEvent where
     toJSON event = object $ filter ((/=) Null . snd)
-        [ ("key",       toJSON $ getField @"key"          event)
-        , ("user",      toJSON $ getField @"user"         event)
-        , ("userKey",   toJSON $ getField @"userKey"      event)
-        , ("value",     toJSON $ getField @"value"        event)
-        , ("default",   toJSON $ getField @"defaultValue" event)
-        , ("version",   toJSON $ getField @"version"      event)
-        , ("variation", toJSON $ getField @"variation"    event)
-        , ("reason",    toJSON $ getField @"reason"       event)
+        [ ("key",         toJSON $ getField @"key"          event)
+        , ("user",        toJSON $ getField @"user"         event)
+        , ("userKey",     toJSON $ getField @"userKey"      event)
+        , ("value",       toJSON $ getField @"value"        event)
+        , ("default",     toJSON $ getField @"defaultValue" event)
+        , ("version",     toJSON $ getField @"version"      event)
+        , ("variation",   toJSON $ getField @"variation"    event)
+        , ("reason",      toJSON $ getField @"reason"       event)
+        , ("contextKind", let c = (getField @"contextKind" event) in
+            if c == ContextKindUser then Null else toJSON c)
         ]
 
 instance EventKind FeatureEvent where
@@ -169,6 +184,7 @@
     , variation    = getField @"variation" event
     , reason       = if includeReason || getField @"forceIncludeReason" event
         then pure $ getField @"reason" event else Nothing
+    , contextKind  = userGetContextKind user
     }
 
 data CustomEvent = CustomEvent
@@ -177,6 +193,7 @@
     , userKey     :: !(Maybe Text)
     , metricValue :: !(Maybe Double)
     , value       :: !(Maybe Value)
+    , contextKind :: !ContextKind
     } deriving (Generic, Show)
 
 instance ToJSON CustomEvent where
@@ -186,11 +203,32 @@
         , ("userKey",     toJSON $ getField @"userKey"     ctx)
         , ("metricValue", toJSON $ getField @"metricValue" ctx)
         , ("data",        toJSON $ getField @"value"       ctx)
+        , ("contextKind", let c = (getField @"contextKind" ctx) in
+            if c == ContextKindUser then Null else toJSON c)
         ]
 
 instance EventKind CustomEvent where
     eventKind _ = "custom"
 
+data AliasEvent = AliasEvent
+    { key                 :: !Text
+    , contextKind         :: !ContextKind
+    , previousKey         :: !Text
+    , previousContextKind :: !ContextKind
+    }
+    deriving (Generic, Show)
+
+instance ToJSON AliasEvent where
+    toJSON ctx = object $ filter ((/=) Null . snd)
+        [ ("key",                 toJSON $ getField @"key"                 ctx)
+        , ("contextKind",         toJSON $ getField @"contextKind"         ctx)
+        , ("previousKey",         toJSON $ getField @"previousKey"         ctx)
+        , ("previousContextKind", toJSON $ getField @"previousContextKind" ctx)
+        ]
+
+instance EventKind AliasEvent where
+    eventKind _ = "alias"
+
 data BaseEvent event = BaseEvent
     { creationDate :: Natural
     , event        :: event
@@ -212,6 +250,7 @@
     | EventTypeCustom   !(BaseEvent CustomEvent)
     | EventTypeIndex    !(BaseEvent IndexEvent)
     | EventTypeDebug    !(BaseEvent DebugEvent)
+    | EventTypeAlias    !(BaseEvent AliasEvent)
 
 instance ToJSON EventType where
     toJSON event = case event of
@@ -221,6 +260,7 @@
         EventTypeCustom   x -> toJSON x
         EventTypeIndex    x -> toJSON x
         EventTypeDebug    x -> toJSON x
+        EventTypeAlias    x -> toJSON x
 
 newUnknownFlagEvent :: Text -> Value -> EvaluationReason -> EvalEvent
 newUnknownFlagEvent key defaultValue reason = EvalEvent
