diff --git a/libpurple/purplesavedpresence.h b/libpurple/purplesavedpresence.h
--- a/libpurple/purplesavedpresence.h
+++ b/libpurple/purplesavedpresence.h
@@ -39,17 +39,6 @@
                      SAVED_PRESENCE, GObject)
 
 /**
- * purple_saved_presence_new:
- *
- * Creates a new saved_presence instance.
- *
- * Returns: (transfer full): The new instance.
- *
- * Since: 3.0.0
- */
-PurpleSavedPresence *purple_saved_presence_new(void);
-
-/**
  * purple_saved_presence_get_last_used:
  * @presence: The instance.
  *
@@ -98,6 +87,19 @@
 void purple_saved_presence_set_use_count(PurpleSavedPresence *presence, guint use_count);
 
 /**
+ * purple_saved_presence_get_id:
+ * @presence: The instance.
+ *
+ * Gets the identifier for @presence. If an identifier was not specified when
+ * @presence was created a random one will have been generated.
+ *
+ * Returns: The identifier for @presence.
+ *
+ * Since: 3.0.0
+ */
+const char *purple_saved_presence_get_id(PurpleSavedPresence *presence);
+
+/**
  * purple_saved_presence_get_name:
  * @presence: The instance.
  *
# HG changeset patch
# Node ID 6f7cb0a641d9
# Parent  375540fa458f
diff --git a/libpurple/purplesavedpresence.c b/libpurple/purplesavedpresence.c
--- a/libpurple/purplesavedpresence.c
+++ b/libpurple/purplesavedpresence.c
@@ -32,8 +32,8 @@
 	GDateTime *last_used;
 	guint use_count;
 
+	char *id;
 	char *name;
-	char *escaped_name;
 
 	PurplePresencePrimitive primitive;
 	char *message;
@@ -44,8 +44,8 @@
 	PROP_0,
 	PROP_LAST_USED,
 	PROP_USE_COUNT,
+	PROP_ID,
 	PROP_NAME,
-	PROP_ESCAPED_NAME,
 	PROP_PRIMITIVE,
 	PROP_MESSAGE,
 	PROP_EMOJI,
@@ -56,9 +56,39 @@
 G_DEFINE_TYPE(PurpleSavedPresence, purple_saved_presence, G_TYPE_OBJECT)
 
 /******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_saved_presence_set_id(PurpleSavedPresence *presence, const char *id) {
+	g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence));
+
+	if(!purple_strequal(presence->id, id)) {
+		g_free(presence->id);
+		presence->id = g_strdup(id);
+
+		g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_ID]);
+	}
+}
+
+/******************************************************************************
  * GObject Implementation
  *****************************************************************************/
 static void
+purple_saved_presence_constructed(GObject *obj) {
+	PurpleSavedPresence *presence = PURPLE_SAVED_PRESENCE(obj);
+
+	G_OBJECT_CLASS(purple_saved_presence_parent_class)->constructed(obj);
+
+	if(purple_strempty(presence->id)) {
+		char *id = g_uuid_string_random();
+
+		purple_saved_presence_set_id(presence, id);
+
+		g_free(id);
+	}
+}
+
+static void
 purple_saved_presence_set_property(GObject *obj, guint param_id,
                                    const GValue *value, GParamSpec *pspec)
 {
@@ -73,6 +103,9 @@
 			purple_saved_presence_set_use_count(presence,
 			                                    g_value_get_uint(value));
 			break;
+		case PROP_ID:
+			purple_saved_presence_set_id(presence, g_value_get_string(value));
+			break;
 		case PROP_NAME:
 			purple_saved_presence_set_name(presence,
 			                               g_value_get_string(value));
@@ -110,14 +143,14 @@
 			g_value_set_uint(value,
 			                 purple_saved_presence_get_use_count(presence));
 			break;
+		case PROP_ID:
+			g_value_set_string(value,
+			                   purple_saved_presence_get_id(presence));
+			break;
 		case PROP_NAME:
 			g_value_set_string(value,
 			                   purple_saved_presence_get_name(presence));
 			break;
-		case PROP_ESCAPED_NAME:
-			g_value_set_string(value,
-			                   purple_saved_presence_get_escaped_name(presence));
-			break;
 		case PROP_PRIMITIVE:
 			g_value_set_enum(value,
 			                 purple_saved_presence_get_primitive(presence));
@@ -146,8 +179,8 @@
 
 	g_clear_pointer(&presence->last_used, g_date_time_unref);
 
+	g_clear_pointer(&presence->id, g_free);
 	g_clear_pointer(&presence->name, g_free);
-	g_clear_pointer(&presence->escaped_name, g_free);
 	g_clear_pointer(&presence->message, g_free);
 	g_clear_pointer(&presence->emoji, g_free);
 
@@ -158,9 +191,10 @@
 purple_saved_presence_class_init(PurpleSavedPresenceClass *klass) {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
+	obj_class->constructed = purple_saved_presence_constructed;
+	obj_class->finalize = purple_saved_presence_finalize;
 	obj_class->get_property = purple_saved_presence_get_property;
 	obj_class->set_property = purple_saved_presence_set_property;
-	obj_class->finalize = purple_saved_presence_finalize;
 
 	/**
 	 * PurpleSavedPresence:last-used:
@@ -189,6 +223,20 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
+	 * PurpleSavedPresence:id:
+	 *
+	 * The identifier of the saved presence. If not specified, one will be
+	 * randomly generated.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_ID] = g_param_spec_string(
+		"id", "id",
+		"The identifier of this saved presence.",
+		NULL,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurpleSavedPresence:name:
 	 *
 	 * The name of the saved presence.
@@ -202,20 +250,6 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleSavedPresence:escaped-name:
-	 *
-	 * An escaped version of [property@PurpleSavedPresence:name] that's
-	 * suitable for serialization.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_ESCAPED_NAME] = g_param_spec_string(
-		"escaped-name", "escaped-name",
-		"The escaped version of the name.",
-		NULL,
-		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	/**
 	 * PurpleSavedPresence:primitive:
 	 *
 	 * The [enum@Purple.StatusPrimitive] for this saved presence.
@@ -261,11 +295,6 @@
 /******************************************************************************
  * Public API
  *****************************************************************************/
-PurpleSavedPresence *
-purple_saved_presence_new(void) {
-	return g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
-}
-
 GDateTime *
 purple_saved_presence_get_last_used(PurpleSavedPresence *presence) {
 	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL);
@@ -312,6 +341,13 @@
 }
 
 const char *
+purple_saved_presence_get_id(PurpleSavedPresence *presence) {
+	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL);
+
+	return presence->id;
+}
+
+const char *
 purple_saved_presence_get_name(PurpleSavedPresence *presence) {
 	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL);
 
@@ -325,33 +361,13 @@
 	g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence));
 
 	if(!purple_strequal(presence->name, name)) {
-		GObject *obj = G_OBJECT(presence);
-
 		g_free(presence->name);
 		presence->name = g_strdup(name);
 
-		g_free(presence->escaped_name);
-		if(!purple_strempty(presence->name)) {
-			presence->escaped_name = g_uri_escape_string(presence->name, NULL,
-			                                             TRUE);
-		} else {
-			presence->escaped_name = NULL;
-		}
-
-		g_object_freeze_notify(obj);
-		g_object_notify_by_pspec(obj, properties[PROP_NAME]);
-		g_object_notify_by_pspec(obj, properties[PROP_ESCAPED_NAME]);
-		g_object_thaw_notify(obj);
+		g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_NAME]);
 	}
 }
 
-const char *
-purple_saved_presence_get_escaped_name(PurpleSavedPresence *presence) {
-	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL);
-
-	return presence->escaped_name;
-}
-
 PurplePresencePrimitive
 purple_saved_presence_get_primitive(PurpleSavedPresence *presence) {
 	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence),
diff --git a/libpurple/tests/test_saved_presence.c b/libpurple/tests/test_saved_presence.c
--- a/libpurple/tests/test_saved_presence.c
+++ b/libpurple/tests/test_saved_presence.c
@@ -21,40 +21,17 @@
 #include <purple.h>
 
 /******************************************************************************
- * Callback helpers
- *****************************************************************************/
-static void
-test_purple_saved_presence_notify_called(G_GNUC_UNUSED GObject *obj,
-                                         G_GNUC_UNUSED GParamSpec *pspec,
-                                         gpointer data)
-{
-	guint *counter = data;
-
-	*counter = *counter + 1;
-}
-
-/******************************************************************************
  * Tests
  *****************************************************************************/
 static void
-test_purple_saved_presence_new(void) {
-	PurpleSavedPresence *presence = NULL;
-
-	presence = purple_saved_presence_new();
-	g_assert_true(PURPLE_IS_SAVED_PRESENCE(presence));
-
-	g_clear_object(&presence);
-}
-
-static void
 test_purple_saved_presence_properties(void) {
 	PurpleSavedPresence *presence = NULL;
 	PurplePresencePrimitive primitive;
 	GDateTime *last_used = NULL;
 	GDateTime *last_used1 = NULL;
 	guint use_count;
+	char *id = NULL;
 	char *name = NULL;
-	char *escaped_name = NULL;
 	char *message = NULL;
 	char *emoji = NULL;
 
@@ -68,6 +45,7 @@
 		PURPLE_TYPE_SAVED_PRESENCE,
 		"last-used", last_used,
 		"use-count", 123,
+		"id", "leeloo dallas multipass",
 		"name", "my saved status",
 		"primitive", PURPLE_PRESENCE_PRIMITIVE_STREAMING,
 		"message", "I'm live on twitch at https://twitch.tv/rw_grim/",
@@ -79,8 +57,8 @@
 		presence,
 		"last-used", &last_used1,
 		"use-count", &use_count,
+		"id", &id,
 		"name", &name,
-		"escaped-name", &escaped_name,
 		"primitive", &primitive,
 		"message", &message,
 		"emoji", &emoji,
@@ -93,12 +71,12 @@
 
 	g_assert_cmpuint(use_count, ==, 123);
 
+	g_assert_cmpstr(id, ==, "leeloo dallas multipass");
+	g_clear_pointer(&id, g_free);
+
 	g_assert_cmpstr(name, ==, "my saved status");
 	g_clear_pointer(&name, g_free);
 
-	g_assert_cmpstr(escaped_name, ==, "my%20saved%20status");
-	g_clear_pointer(&escaped_name, g_free);
-
 	g_assert_cmpint(primitive, ==, PURPLE_PRESENCE_PRIMITIVE_STREAMING);
 
 	g_assert_cmpstr(message, ==,
@@ -113,29 +91,15 @@
 }
 
 static void
-test_purple_saved_presence_escaped_name(void) {
+test_purple_saved_presence_generates_id(void) {
 	PurpleSavedPresence *presence = NULL;
-	guint counter = 0;
-
-	presence = g_object_new(
-		PURPLE_TYPE_SAVED_PRESENCE,
-		"name", "{\"text/json\":null}",
-		NULL);
+	const char *id = NULL;
 
-	g_signal_connect(presence, "notify",
-	                 G_CALLBACK(test_purple_saved_presence_notify_called),
-	                 &counter);
+	presence = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
-	g_assert_cmpstr(purple_saved_presence_get_name(presence), ==,
-	                "{\"text/json\":null}");
-	g_assert_cmpstr(purple_saved_presence_get_escaped_name(presence), ==,
-	                "%7B%22text%2Fjson%22%3Anull%7D");
-
-	purple_saved_presence_set_name(presence, "🐧🐶🐱");
-	g_assert_cmpstr(purple_saved_presence_get_escaped_name(presence), ==,
-	                "🐧🐶🐱");
-
-	g_assert_cmpuint(counter, ==, 2);
+	id = purple_saved_presence_get_id(presence);
+	g_assert_nonnull(id);
+	g_assert_cmpstr(id, !=, "");
 
 	g_clear_object(&presence);
 }
@@ -147,7 +111,7 @@
 
 static void
 test_purple_saved_presence_equal_null_a(void) {
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	g_assert_false(purple_saved_presence_equal(NULL, b));
 
@@ -156,7 +120,7 @@
 
 static void
 test_purple_saved_presence_equal_null_b(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	g_assert_false(purple_saved_presence_equal(a, NULL));
 
@@ -165,8 +129,8 @@
 
 static void
 test_purple_saved_presence_equal_default(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	g_assert_true(purple_saved_presence_equal(a, b));
 
@@ -176,8 +140,8 @@
 
 static void
 test_purple_saved_presence_equal_last_used(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 	GDateTime *now = g_date_time_new_now_utc();
 	GDateTime *yesterday = g_date_time_add_days(now, -1);
 
@@ -209,8 +173,8 @@
 
 static void
 test_purple_saved_presence_equal_use_count(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	/* Set the use-count of a to 100. */
 	purple_saved_presence_set_use_count(a, 100);
@@ -230,8 +194,8 @@
 
 static void
 test_purple_saved_presence_equal_name(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	/* Set the name of a. */
 	purple_saved_presence_set_name(a, "present");
@@ -255,8 +219,8 @@
 
 static void
 test_purple_saved_presence_equal_primitive(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	/* Set the primitive of a to streaming. */
 	purple_saved_presence_set_primitive(a,
@@ -278,8 +242,8 @@
 
 static void
 test_purple_saved_presence_equal_message(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	/* Set the message for a. */
 	purple_saved_presence_set_message(a, "sleeping...");
@@ -299,8 +263,8 @@
 
 static void
 test_purple_saved_presence_equal_emoji(void) {
-	PurpleSavedPresence *a = purple_saved_presence_new();
-	PurpleSavedPresence *b = purple_saved_presence_new();
+	PurpleSavedPresence *a = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
+	PurpleSavedPresence *b = g_object_new(PURPLE_TYPE_SAVED_PRESENCE, NULL);
 
 	/* Set the emoji for a. */
 	purple_saved_presence_set_emoji(a, "💤");
@@ -325,12 +289,11 @@
 main(gint argc, gchar *argv[]) {
 	g_test_init(&argc, &argv, NULL);
 
-	g_test_add_func("/saved-presence/new",
-	                test_purple_saved_presence_new);
 	g_test_add_func("/saved-presence/properties",
 	                test_purple_saved_presence_properties);
-	g_test_add_func("/saved-presence/escaped-name",
-	                test_purple_saved_presence_escaped_name);
+
+	g_test_add_func("/saved-presence/generates-id",
+	                test_purple_saved_presence_generates_id);
 
 	g_test_add_func("/saved-presence/equal/null_null",
 	                test_purple_saved_presence_equal_null_null);
