Send welcome message to users

APPLIES TO: yesSDK v4 no SDK v3

The primary goal when creating any bot is to engage your user in a meaningful conversation. One of the best ways to achieve this goal is to ensure that from the moment a user first connects, they understand your bot’s main purpose and capabilities, the reason your bot was created. This article provides code examples to help you welcome users to your bot.

Prerequisites

About this sample code

This sample code shows how to detect and welcome new users when they are initially connected to your bot. The following diagram shows the logic flow for this bot.

The two main events encountered by the bot are:

  • OnMembersAddedAsync which is called whenever a new user is connected to your bot
  • OnMessageActivityAsync which is called whenever a new user input is received.

welcome user logic flow

Whenever a new user is connected, they are provided with a WelcomeMessage, InfoMessage, and PatternMessage by the bot. When a new user input is received, WelcomeUserState is checked to see if DidBotWelcomeUser is set to true. If not, an initial welcome user message is returned to the user.

Create user object

The user state object is created at startup and dependency injected into the bot constructor.

Startup.cs

// Create the User state.
services.AddSingleton<UserState>();

// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, WelcomeUserBot>();

WelcomeUserBot.cs

private BotState _userState;

// Initializes a new instance of the "WelcomeUserBot" class.
public WelcomeUserBot(UserState userState)
{
    _userState = userState;
}

Create property accessors

We now create a property accessor that provides us a handle to WelcomeUserState inside the OnMessageActivityAsync method. Then call the GetAsync method to get the properly scoped key. We then save user state data after each user input iteration using the SaveChangesAsync method.

Bots\WelcomeUserBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
    var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState());
    // Save any state changes.
    await _userState.SaveChangesAsync(turnContext);
}

Detect and greet newly connected users

In WelcomeUserBot, we check for an activity update using OnMembersAddedAsync() to see if a new user has been added to the conversation and then send them a set of three initial welcome messages WelcomeMessage, InfoMessage and PatternMessage. Complete code for this interaction is shown below.

WelcomeUserBot.cs

public class WelcomeUserBot : ActivityHandler
{
    // Messages sent to the user.
    private const string WelcomeMessage = "This is a simple Welcome Bot sample. This bot will introduce you " +
                                            "to welcoming and greeting users. You can say 'intro' to see the " +
                                            "introduction card. If you are running this bot in the Bot Framework " +
                                            "Emulator, press the 'Start Over' button to simulate user joining " +
                                            "a bot or a channel";

    private const string InfoMessage = "You are seeing this message because the bot received at least one " +
                                        "'ConversationUpdate' event, indicating you (and possibly others) " +
                                        "joined the conversation. If you are using the emulator, pressing " +
                                        "the 'Start Over' button to trigger this event again. The specifics " +
                                        "of the 'ConversationUpdate' event depends on the channel. You can " +
                                        "read more information at: " +
                                        "https://aka.ms/about-botframework-welcome-user";

    private const string PatternMessage = "It is a good pattern to use this event to send general greeting" +
                                          "to user, explaining what your bot can do. In this example, the bot " +
                                          "handles 'hello', 'hi', 'help' and 'intro'. Try it now, type 'hi'";
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (var member in membersAdded)
    {
        if (member.Id != turnContext.Activity.Recipient.Id)
        {
            await turnContext.SendActivityAsync($"Hi there - {member.Name}. {WelcomeMessage}", cancellationToken: cancellationToken);
            await turnContext.SendActivityAsync(InfoMessage, cancellationToken: cancellationToken);
            await turnContext.SendActivityAsync(PatternMessage, cancellationToken: cancellationToken);
        }
    }
}

Welcome new user and discard initial input

It is also important to consider when your user’s input might actually contain useful information, and this may vary for each channel. To ensure your user has a good experience on all possible channels, we check the status flag didBotWelcomeUser and if this is "false", we do not process the initial user input. We instead provide the user with an initial welcome message. The bool welcomedUserProperty is then set to "true", stored in UserState and our code will now process this user's input from all additional message activities.

WelcomeUserBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var welcomeUserStateAccessor = _userState.CreateProperty<WelcomeUserState>(nameof(WelcomeUserState));
    var didBotWelcomeUser = await welcomeUserStateAccessor.GetAsync(turnContext, () => new WelcomeUserState());

    if (didBotWelcomeUser.DidBotWelcomeUser == false)
    {
        didBotWelcomeUser.DidBotWelcomeUser = true;

        // the channel should sends the user name in the 'From' object
        var userName = turnContext.Activity.From.Name;

        await turnContext.SendActivityAsync($"You are seeing this message because this was your first message ever to this bot.", cancellationToken: cancellationToken);
        await turnContext.SendActivityAsync($"It is a good practice to welcome the user and provide personal greeting. For example, welcome {userName}.", cancellationToken: cancellationToken);
    }

Process additional input

Once a new user has been welcomed, user input information is evaluated for each message turn and the bot provides a response based on the context of that user input. The following code shows the decision logic used to generate that response.

An input of 'intro' or 'help' calls the function SendIntroCardAsync to present the user with an informational hero card. That code is examined in the next section of this article.

WelcomeUserBot.cs

// This example hardcodes specific utterances. You should use LUIS or QnA for more advance language understanding.
var text = turnContext.Activity.Text.ToLowerInvariant();
switch (text)
{
    case "hello":
    case "hi":
        await turnContext.SendActivityAsync($"You said {text}.", cancellationToken: cancellationToken);
        break;
    case "intro":
    case "help":
        await SendIntroCardAsync(turnContext, cancellationToken);
        break;
    default:
        await turnContext.SendActivityAsync(WelcomeMessage, cancellationToken: cancellationToken);
        break;
}

Using hero card greeting

As mentioned above, some user inputs generate a Hero Card in response to their request. You can learn more about hero card greetings here Send an Intro Card. Below is the code required to create this bot's hero card response.

WelcomeUserBot.cs

private static async Task SendIntroCardAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
    var card = new HeroCard();
    card.Title = "Welcome to Bot Framework!";
    card.Text = @"Welcome to Welcome Users bot sample! This Introduction card
                 is a great way to introduce your Bot to the user and suggest
                 some things to get them started. We use this opportunity to
                 recommend a few next steps for learning more creating and deploying bots.";
    card.Images = new List<CardImage>() { new CardImage("https://aka.ms/bf-welcome-card-image") };
    card.Buttons = new List<CardAction>()
    {
        new CardAction(ActionTypes.OpenUrl, "Get an overview", null, "Get an overview", "Get an overview", "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"),
        new CardAction(ActionTypes.OpenUrl, "Ask a question", null, "Ask a question", "Ask a question", "https://stackoverflow.com/questions/tagged/botframework"),
        new CardAction(ActionTypes.OpenUrl, "Learn how to deploy", null, "Learn how to deploy", "Learn how to deploy", "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"),
    };
    
    var response = MessageFactory.Attachment(card.ToAttachment());
    await turnContext.SendActivityAsync(response, cancellationToken);
}

Test the bot

Download and install the latest Bot Framework Emulator

  1. Run the sample locally on your machine. If you need instructions, refer to the README file for C# Sample or JS Sample.
  2. Use the emulator to test the bot as shown below.

test welcome bot sample

Test hero card greeting.

test welcome bot card

Additional Resources

Learn more about various media responses in Add media to messages.

Next steps