---
title: Example – Create audience criteria
slug: cms-12/docs/example-create-your-own-visitor-group-criteria
docTags: 
createdAt: 2026-08-10T15:55:53.000Z
---

(Thanks to [Ted and Gustaf](https://tedgustaf.com/) for this example.)

One usage scenario could be to check for a cookie that says the visitor has previously completed a purchase on the website and is a returning customer.

The example uses the following steps:

1. Creating the settings and criterion classes
2. Implementing the settings class
3. Implementing the criterion class
4. Testing the criterion

## Create the settings and criterion classes

Audience criteria require a settings class and a criterion class. The settings class is used to persist any settings available to editors when creating an audience. The criterion class contains the logic to determine whether or not a visitor belongs to the audience.

You should create the two classes in a suitable folder structure:

![Create the settings and criterion classes](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/rt8q6mn4X5zEG7bh2U4Cb-20260722-184805.png "create_classes.png")

## Implement the settings class

The only setting required for this audience criterion is the cookie name you should look for.

1. First, make the `CookieExistsCriterionSettings` class inherit the `CriterionModelBase` class:

```csharp
public class CookieExistsCriterionSettings : CriterionModelBase
```

2. Add a `public` property to let editors specify the cookie name:

```csharp
[Required]
public string CookieName {
  get;
  set;
}
```

3. If you need custom validation logic when a criterion is saved, you can make your settings class implement the `IValidateCriterionModel` interface (this is optional). By implementing that interface’s `Validate` method, you can customize how settings are validated before saving a criterion for an audience.
   The abstract `CriterionModelBase` class requires you to implement the `Copy()` method. Because you are not using complex reference types, you can implement it by returning a shallow copy as shown (see [Create custom audience criteria](https://docs.developers.optimizely.com/content-management-system/docs/developing-custom-visitor-group-criteria)):

```csharp
public override ICriterionModel Copy() {
  return ShallowCopy();
}
```

This is the complete `CookieExistsCriterionSettings` class:

```csharp
public class CookieExistsCriterionSettings: CriterionModelBase {
  [Required]
  public string CookieName {
    get;
    set;
  }
  public override ICriterionModel Copy() {
    return ShallowCopy();
  }
}
```

## Implement the criterion class

1. Make the `CookieExistsCriterion` class inherit the abstract `CriterionBase` class with the settings class as the type parameter:

```csharp
public class CookieExistsCriterion : CriterionBase<CookieExistsCriterionSettings>
```

2. Add a `VisitorGroupCriterion` attribute to set the category, name, and description of the criterion (for more available `VisitorGroupCriterion` properties, see [Create custom audience criteria](https://docs.developers.optimizely.com/content-management-system/docs/developing-custom-visitor-group-criteria):

```csharp
[VisitorGroupCriterion(   
  Category = "Technical",
  DisplayName = "Cookie Exists",
  Description = "Checks if a specific cookie exists")]
```

3. The abstract `CriterionBase` class requires you to implement an `IsMatch()` method, which determines whether the current user matches this audience criterion. You should check if a specific cookie exists based on the criterion settings:

```csharp
public override bool IsMatch(IPrincipal principal, HttpContextBase httpContext) {
  return httpContext.Request.Cookies[Model.CookieName] != null;
}
```

The criterion class appears as follows:

```csharp
[VisitorGroupCriterion(
  Category = "Technical",
  DisplayName = "Cookie Exists",
  Description = "Checks if a specific cookie exists")]

public class CookieExistsCriterion: CriterionBase<CookieExistsCriterionSettings> {
  public override bool IsMatch(IPrincipal principal, HttpContextBase httpContext) {
    return httpContext.Request.Cookies[Model.CookieName] != null;
  }
}
```

:::hint{type="info"}
**Note**
You access the criterion settings instance through the Model property.
:::

## Test the criterion

To test the criterion, create an audience using the cookie criterion.

1. Set the cookie name to **.EPiServerLogin**, the name of the cookie created when a user logs in to Episerver:
   ![Set the cookie name to .EPiServerLogin](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/8rmmQjN87xCRbEp20T416-20260722-184805.png "cookieexists.png")
   If you are on CMS version 10 or 11, it will look like this:
   ![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/uUAjy3YyNULPIJ4Kl_M1P-20260722-184805.png "cookie_exists.png")
2. Select some content in the editor that should only be displayed to users currently logged in to Episerver.
   ![Select some content in the editor that should only be displayed to users currently logged in](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/VkiZXJb459hsrjQFR6dbA-20260722-184805.png "personalizecontent.png")
3. Click **Personalized Content** and select the  **Episerver User** audience.
   ![Click Personalized content icon](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/kDTEnujnpucf1fNZbY6aD-20260722-184805.png "selectvisitorgroup.png")
   This content is now only displayed to users logged into Episerver:

![Content is displayed to logged in users](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/nN_ATSQRwsDS-vzjAbtiZ-20260722-184805.png "personalizedcontenttinymce.png")

After publishing the page, you see this:

![Published page display with personalization](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/oytg99OhCLM2MQzSKPJxe-20260722-184805.png "logged_in2.png")

However, if you log out of Episerver, you no longer see the personalized content.

![Published page display without personalization](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/5mL_RI-fLF9tPpS2EdxOn-20260722-184805.png "not_logged_in.png")
