Configure advanced filter for content browsing
Overview
With so much content being created, either by developers as official content or by players as user-generated content (UGC), browsing content can become difficult and time-consuming. AccelByte Gaming Services (AGS) offers a way to let players choose and filter content based on their needs, so the player can choose content that reflects their personality, preferences, and style.
In this guide, you will learn how to implement tags, types, and subtypes to content, and also use them to filter content from the game client.
Goals
The goals of this guide are to explain how to:
- Configure predefined tags, types, and subtypes.
- Add tags, types, and subtypes to content.
- Implement content filtering.
Prerequisites
You will need access to:
- The AGS Admin Portal
- The AccelByte Unreal or Unity SDK
- The AccelByte UGC API documentation for further reference
Content tags, types, and subtypes
You can create Types and Tags that can be used to categorize UGC. For example, a custom design for a car might have Vehicle as the Type and Body or Wheels as the Subtype. Tags could also include Car, Vehicle, or Body.
Configure predefined tags
In the Admin Portal under Game Management, click UGC Management and open the Configurations menu.
In the Configurations menu, switch to the Tags tab and click New Tag.
Input the Tag Name. When you're finished, click Add.
The new Tag will be added to the list.
Configure predefined types and subtypes
In the Admin Portal under Game Management, click UGC Management and open the Configurations menu.
In the Configurations menu, click New Type.
Input a name for the new type in the Type Name field. When you're finished, click Add.
The new type will be added to the list. You can also add a subtype by clicking View in the type’s Action menu.
In the Subtypes section, click the New Subtypes button.
Input the Subtype Name. When you're finished, click the Add button.
The new Subtype will be added to the list.
Add tags, types, and subtypes to content
In the Admin Portal, go to UGC Management and click the Contents menu.
Search for the content you want using the provided filters.
Click View under your selected item’s Action column.
On the Content Details Page, click the Edit button next to Type or Subtype.
Select the predefined type and subtype on Edit Type and Subtype screen.
Click Save to confirm the changes.
Click Add More on the Tag field.
Write your new tag, or select from the predefined list.
Click Save to confirm the changes.
Add tags, types, and subtypes to content using the Client SDK
You can use the following function to set the player content metadata, such as tags, types, and subtypes while creating the content:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ChannelId = "YourChannelId";
FAccelByteModelsUGCRequest UGCRequest = {};
UGCRequest.ContentType = "application/octet-stream";
UGCRequest.FileExtension = "bin";
UGCRequest.Name = "Custom sports body";
UGCRequest.Type = "Vehicle";
UGCRequest.SubType = "Body";
UGCRequest.Tags = { "Red", "Sporty"};
ApiClient->UGC.CreateContent(ChannelId, UGCRequest, THandler<FAccelByteModelsUGCResponse>::CreateLambda([](const FAccelByteModelsUGCResponse& Result)
{
// Do something if CreateContent has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if CreateContent has an error
UE_LOG(LogTemp, Log, TEXT("Error CreateContent, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
string channelId = "YourChannelId";
UGCRequest createRequest = new UGCRequest
{
contentType = "application/octet-stream",
fileExtension = "bin",
name = "Custom sports body",
preview = "",
type = "Vehicle",
subtype = "Body",
tags = new[] { "Red", "Sporty" },
customAttributes = new Dictionary<string, object>()
};
AccelBytePlugin.GetUgc().CreateContent(channelId, createRequest, result =>
{
if (result.IsError)
{
// Do something if CreateContent has an error
Debug.Log($"Error CreateContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if CreateContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ChannelId = "YourChannelId";
FAccelByteModelsCreateUGCRequestV2 UGCRequest = {};
UGCRequest.ContentType = "application/octet-stream";
UGCRequest.FileExtension = "bin";
UGCRequest.Name = "Custom sports body";
UGCRequest.Type = "Vehicle";
UGCRequest.SubType = "Body";
UGCRequest.Tags = { "Red", "Sporty"};
ApiClient->UGC.CreateV2Content(ChannelId, UGCRequest, THandler<FAccelByteModelsUGCCreateUGCResponseV2>::CreateLambda([](const FAccelByteModelsUGCCreateUGCResponseV2& Result)
{
// Do something if CreateV2Content has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if CreateV2Content has an error
UE_LOG(LogTemp, Log, TEXT("Error CreateV2Content, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
string channelId = "YourChannelId";
CreateUGCRequestV2 createRequest = new CreateUGCRequestV2
{
contentType = "application/octet-stream",
fileExtension = "bin",
name = "Custom sports body",
preview = "",
type = "Vehicle",
subtype = "Body",
tags = new[] { "Red", "Sporty" },
CustomAttributes = new Dictionary<string, object>()
};
AccelBytePlugin.GetUgc().CreateV2Content(channelId, createRequest, result =>
{
if (result.IsError)
{
// Do something if CreateV2Content has an error
Debug.Log($"Error CreateV2Content, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if CreateV2Content has been successful
}
});
You can use the following function to update the player content metadata, such as tags, types, and subtypes:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ChannelId = "YourChannelId";
FString ContentId = "YourContentId";
FAccelByteModelsUGCUpdateRequest ModifyRequest = {};
ModifyRequest.ContentType = "application/octet-stream";
ModifyRequest.FileExtension = "bin";
ModifyRequest.Name = "Custom sports body";
ModifyRequest.Type = "Vehicle";
ModifyRequest.SubType = "Body";
ModifyRequest.Tags = { "Blue", "Sporty", "Body"};
ModifyRequest.UpdateContentFile = true;
ApiClient->UGC.ModifyContent(ChannelId, ContentId, ModifyRequest, THandler<FAccelByteModelsUGCResponse>::CreateLambda([](const FAccelByteModelsUGCResponse& Result)
{
// Do something if ModifyContent has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if ModifyContent has an error
UE_LOG(LogTemp, Log, TEXT("Error ModifyContent, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
string channelId = "YourChannelId";
string contentId = "YourContentId";
UGCUpdateRequest ModifyRequest = new UGCUpdateRequest
{
ContentType = "application/octet-stream",
FileExtension = "bin",
Name = "Custom sports body",
Preview = "",
Type = "Vehicle",
Subtype = "Body",
Tags = new[] { "Blue", "Sporty", "Body"},
CustomAttributes = new Dictionary<string, object>()
};
AccelBytePlugin.GetUgc().ModifyContent(channelId, contentId,
ModifyRequest, result =>
{
if (result.IsError)
{
// Do something if ModifyContent has an error
Debug.Log($"Error ModifyContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if ModifyContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ChannelId = "YourChannelId";
FString ContentId = "YourContentId";
FAccelByteModelsModifyUGCRequestV2 ModifyRequest = {};
ModifyRequest.Name = "Custom sports body";
ModifyRequest.Type = "Vehicle";
ModifyRequest.SubType = "Body";
ModifyRequest.Tags = { "Blue", "Sporty", "Body"};
ApiClient->UGC.ModifyV2Content(ChannelId, ContentId, ModifyRequest, THandler<FAccelByteModelsUGCModifyUGCResponseV2>::CreateLambda([](const FAccelByteModelsUGCModifyUGCResponseV2& Result)
{
// Do something if ModifyV2Content has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if ModifyV2Content has an error
UE_LOG(LogTemp, Log, TEXT("Error ModifyV2Content, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
string channelId = "YourChannelId";
string contentId = "YourContentId";
ModifyUGCRequestV2 ModifyRequest = new ModifyUGCRequestV2
{
Name = "Custom sports body",
Type = "Vehicle",
Subtype = "Body",
Tags = new[] { "Blue", "Sporty", "Body"},
CustomAttributes = new Dictionary<string, object>()
};
AccelBytePlugin.GetUgc().ModifyV2Content(channelId, contentId,
ModifyRequest, result =>
{
if (result.IsError)
{
// Do something if ModifyV2Content has an error
Debug.Log($"Error ModifyV2Content, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if ModifyV2Content has been successful
}
});
Content filtering
Content filtering is the process of finding, sorting, and displaying UGC based on various criteria, such as tags, keywords, types, etc. Content filtering also helps players to discover and enjoy UGC that matches their preferences, interests, and skill levels.
Search content by name
You can filter the content using its name. Do this with the following function:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ContentName = "Content Name";
FString CreatorName = "";
FString Type = "";
FString Subtype = "";
TArray<FString> Tags = { };
bool bIsOfficial = false;
FString UserId = "";
ApiClient->UGC.SearchContents(ContentName, CreatorName, Type, Subtype, Tags, bIsOfficial, UserId,
THandler<FAccelByteModelsUGCSearchContentsPagingResponse>::CreateLambda([](const FAccelByteModelsUGCSearchContentsPagingResponse& Result)
{
// Do something if SearchContents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchContents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchContents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
SearchContentRequest filterRequest = new SearchContentRequest()
{
name = "Content Name"
};
AccelBytePlugin.GetUgc().SearchContent(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchContent has an error
Debug.Log($"Error SearchContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FAccelByteModelsUGCFilterRequest Filter = {};
Filter.Name = "Content Name";
ApiClient->UGC.SearchV2Contents(Filter,
THandler<FAccelByteModelsUGCGetPaginatedUGCContentsResponse>::CreateLambda([](const FAccelByteModelsUGCGetPaginatedUGCContentsResponse& Result)
{
// Do something if SearchV2Contents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchV2Contents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchV2Contents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
UGCGetContentFilterRequest filterRequest = new UGCGetContentFilterRequest()
{
Name = "Content Name"
};
AccelBytePlugin.GetUgc().SearchV2Contents(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchV2Contents has an error
Debug.Log($"Error SearchV2Contents, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchV2Contents has been successful
}
});
Use tags to filter content
Advanced tag filtering supports &
as an AND operator, |
as an OR operator, and parentheses ()
for priority. E.g:
tags=sporty
tags=sporty&red
tags=sporty|red
tags=sporty&red|classic
tags=sporty&(red|classic)
The precedence of the logical operator is AND > OR, so if there are no parentheses, the AND logical operator will be executed first.
Allowed characters for operand: alphanumeric, underscore _
and dash - \
Allowed characters for operator: &
|
(
) \
The tags=sporty&red|classic
also equals to: tags=sporty,red|classic
and tags=sporty&tags=red|classic
You can use this function to filter the content using tags:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
TArray<FString> Tags = { "Sporty", "Red|Classic" };
ApiClient->UGC.SearchContents(ContentName, CreatorName, Type, Subtype, Tags, bIsOfficial, UserId,
THandler<FAccelByteModelsUGCSearchContentsPagingResponse>::CreateLambda([](const FAccelByteModelsUGCSearchContentsPagingResponse& Result)
{
// Do something if SearchContents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchContents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchContents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
SearchContentRequest filterRequest = new SearchContentRequest()
{
tags = new[] { "Sporty", "Red|Classic" }
};
AccelBytePlugin.GetUgc().SearchContent(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchContent has an error
Debug.Log($"Error SearchContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FAccelByteModelsUGCFilterRequest Filter = {};
Filter.Tags = { "Sporty", "Red|Classic" };
ApiClient->UGC.SearchV2Contents(Filter,
THandler<FAccelByteModelsUGCGetPaginatedUGCContentsResponse>::CreateLambda([](const FAccelByteModelsUGCGetPaginatedUGCContentsResponse& Result)
{
// Do something if SearchV2Contents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchV2Contents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchV2Contents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
UGCGetContentFilterRequest filterRequest = new UGCGetContentFilterRequest()
{
Tags = new[] { "Sporty", "Red|Classic" }
};
AccelBytePlugin.GetUgc().SearchV2Contents(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchV2Contents has an error
Debug.Log($"Error SearchV2Contents, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchV2Contents has been successful
}
});
Use types and subtypes to filter content
You can use this function to filter the content using types and subtypes:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ContentName = "";
FString CreatorName = "";
FString Type = "Content Type";
FString Subtype = "Content Subtype";
TArray<FString> Tags = { };
bool bIsOfficial = false;
FString UserId = "";
ApiClient->UGC.SearchContents(ContentName, CreatorName, Type, Subtype, Tags, bIsOfficial, UserId,
THandler<FAccelByteModelsUGCSearchContentsPagingResponse>::CreateLambda([](const FAccelByteModelsUGCSearchContentsPagingResponse& Result)
{
// Do something if SearchContents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchContents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchContents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}));
SearchContentRequest filterRequest = new SearchContentRequest()
{
type = "Content Type",
subtype = "Content Subtype"
};
AccelBytePlugin.GetUgc().SearchContent(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchContent has an error
Debug.Log($"Error SearchContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FAccelByteModelsUGCFilterRequest Filter = {};
Filter.Type = "Content Type";
Filter.SubType = "Content Subtype";
int32 Limit = 1000;
int32 Offset = 0;
EAccelByteUGCContentSortBy SortBy = EAccelByteUGCContentSortBy::CREATED_TIME_DESC;
ApiClient->UGC.SearchV2Contents(Filter,
THandler<FAccelByteModelsUGCGetPaginatedUGCContentsResponse>::CreateLambda([](const FAccelByteModelsUGCGetPaginatedUGCContentsResponse& Result)
{
// Do something if SearchV2Contents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchV2Contents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchV2Contents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}), Limit, Offset, SortBy);
UGCGetContentFilterRequest filterRequest = new UGCGetContentFilterRequest()
{
Type = "Content Type",
SubType = "Content Subtype"
};
AccelBytePlugin.GetUgc().SearchV2Contents(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchV2Contents has an error
Debug.Log($"Error SearchV2Contents, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchV2Contents has been successful
}
});
Sort the content
You can use the sorting field to customize how you view the UGC in the game. AGS supports sorting the list of content based on the like count, created time, download count, and content name.
Here is the list of supported sorting options:
- createdTime, createdTime:desc, createdTime:asc
- download, download:desc, download:asc
- like, like:desc, like:asc
- name, name:desc, name:asc
For example, if you want to see the most recent UGC, you can use createdTime:desc
to sort by the creation date in descending order. If you want to see the most popular UGC, you can use like:desc`` to sort by the number of likes in descending order. If you want to see the UGC in alphabetical order, you can use
name:asc` to sort by the name in ascending order. You can also use download to sort by the number of downloads.
You can use this function to sort the content:
- Unreal Engine V1
- Unity V1
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString ContentName = "Content Name";
FString CreatorName = "Creator Name";
FString Type = "Content Type";
FString Subtype = "Content Subtype";
TArray<FString> Tags = { "Sporty", "Red|Brown" };
bool bIsOfficial = false;
FString UserId = "Player User Id";
int32 Limit = 1000;
int32 Offset = 0;
EAccelByteUgcSortBy SortBy = EAccelByteUgcSortBy::DATE;
EAccelByteUgcOrderBy OrderBy = EAccelByteUgcOrderBy::DESC;
ApiClient->UGC.SearchContents(ContentName, CreatorName, Type, Subtype, Tags, bIsOfficial, UserId,
THandler<FAccelByteModelsUGCSearchContentsPagingResponse>::CreateLambda([](const FAccelByteModelsUGCSearchContentsPagingResponse& Result)
{
// Do something if SearchContents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchContents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchContents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}), SortBy, OrderBy, Limit, Offset);
SearchContentRequest filterRequest = new SearchContentRequest()
{
name = "Content Name",
type = "Content Type",
subtype = "Content Subtype",
tags = new[] { "Sporty", "Red|Brown" },
limit = 1000,
offset = 0,
sortBy = UGCSortBy.DATE,
orderBy = UGCOrderBy.DESC
};
AccelBytePlugin.GetUgc().SearchContent(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchContent has an error
Debug.Log($"Error SearchContent, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchContent has been successful
}
});
- Unreal Engine V2
- Unity V2
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FAccelByteModelsUGCFilterRequest Filter = {};
Filter.Name = "Content Name";
Filter.Type = "Content Type";
Filter.SubType = "Content Subtype";
Filter.Tags = { "Sporty", "Red|Brown" };
int32 Limit = 1000;
int32 Offset = 0;
EAccelByteUGCContentSortBy SortBy = EAccelByteUGCContentSortBy::CREATED_TIME_DESC;
ApiClient->UGC.SearchV2Contents(Filter,
THandler<FAccelByteModelsUGCGetPaginatedUGCContentsResponse>::CreateLambda([](const FAccelByteModelsUGCGetPaginatedUGCContentsResponse& Result)
{
// Do something if SearchV2Contents has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if SearchV2Contents has an error
UE_LOG(LogTemp, Log, TEXT("Error SearchV2Contents, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}), Limit, Offset, SortBy);
UGCGetContentFilterRequest filterRequest = new UGCGetContentFilterRequest()
{
Name = "Content Name",
Type = "Content Type",
SubType = "Content Subtype",
Tags = new[] { "Sporty", "Red|Brown" }
};
int limit = 1000;
int offset = 0;
UGCContentSortBy sortBy = UGCContentSortBy.CreatedTimeDesc;
AccelBytePlugin.GetUgc().SearchV2Contents(filterRequest, result =>
{
if (result.IsError)
{
// Do something if SearchV2Contents has an error
Debug.Log($"Error SearchV2Contents, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
}
else
{
// Do something if SearchV2Contents has been successful
}
}, limit, offset, sortBy);