Moderate dating and adults-only apps

If every member of your app is an adult, start from the General built-in policy and confirm each member's age, then copy and change it if your members shouldn't see explicit images. Your app must check members' ages itself: CalmLens doesn't verify them.

Choose a policy

Your appPolicyWhy
A community where members share explicit images and video on purposeGeneral, unchangedExplicit images and video are age-restricted, so confirmed adults can see them.
A dating appA copy of General with stricter sexual rulesExplicit images are blocked. Sexual text and people's own contact details are limited, so your app can show them in chat and keep them off profiles.
An adult forum or social app without explicit imagesThe same copy, with two changesExplicit images are blocked, and sexual text and contact details are treated as ordinary content.

Adult communities: General and age confirmation

General allows sexual text and age-restricts adult nudity, sexual activity and other adult images and video. An age-restricted asset isn't served from its plain URL, so a member sees it only when your app passes viewerClaims.ageConfirmed: true for them.

  1. Check each member's age when they join. Check age natively covers the checks built into iOS, Android and browsers, and Age-check responsibilities lists where a check must be reliable rather than self-declared.
  2. Keep age-restricted assets private and issue signed URLs to members who passed, as described in Age-restricted assets.
  3. Pass viewerClaims.ageConfirmed: true on those members' requests, and leave it out for everyone else.

Dating apps: a custom policy

Copy General and change its Sexual and Personal information categories. These are the outcomes that change:

ContentGeneralThis policy
Adult nudity, sexual activity and explicit sexual language in images and videoage-restrictblock
Explicit sexual textallowlimit
Requests or offers for an unpaid sexual encounter, in textallowlimit
Requests or offers for an unpaid sexual encounter, in images and videoage-restrictblock
Promotion of adult content, such as a subscription pageallow in text, age-restrict in images and videoblock
Someone's own contact details and other private detailsallowlimit

Flirtation, innuendo, revealing clothing and non-erotic nudity stay allowed. Paid sexual services, non-consensual sexual content, sexual harassment and other people's private details stay blocked, as they are in General. A private detail that doesn't say whose it is counts as someone else's, so a message that says the number is the sender's own is limited, while a number on its own is blocked.

Create the policy

Duplicate General in Portal › Moderation policies and change the rules below, or copy it through the API:

const response = await client.policies.create({
  "presetId": "general-community",
  "name": "Dating"
});

Then send the policy's complete settings with PATCH /policies/:policyId, replacing these two categories and keeping the other six, and choose it with PUT /projects/:projectId/policy. Manage policies in code and configuration files cover keeping the policy in your repository.

{
  "sexual": {
    "action": "block",
    "allowances": [
      { "name": "Reporting or documentary", "when": ["sexual-documentary"], "action": "allow" },
      { "name": "Support and prevention", "when": ["sexual-support-prevention"], "action": "allow" },
      { "name": "Suggestive content", "when": ["sexual-suggestive"], "action": "allow" },
      { "name": "Revealing clothing", "when": ["sexual-revealing-clothing"], "action": "allow" },
      { "name": "Non-graphic discussion", "when": ["sexual-discussion"], "action": "allow" },
      { "name": "Non-erotic nudity", "when": ["sexual-nudity", "sexual-non-erotic-nudity"], "action": "allow" },
      { "name": "Text", "when": ["sexual-text"], "action": "limit" }
    ],
    "restrictions": [
      { "name": "Paid sexual services", "when": ["sexual-solicitation", "sexual-paid"], "action": "block" },
      { "name": "Explicit sexual language", "when": ["sexual-explicit-language"], "unless": ["sexual-text"], "action": "block" },
      { "name": "Nudity", "when": ["sexual-nudity"], "unless": ["sexual-non-erotic-nudity", "sexual-text"], "action": "block" },
      { "name": "Sexual activity", "when": ["sexual-activity"], "unless": ["sexual-documentary", "sexual-support-prevention", "sexual-discussion", "sexual-text"], "action": "block" },
      { "name": "Non-consensual sexual content", "when": ["sexual-non-consensual"], "unless": ["sexual-documentary", "sexual-support-prevention", "sexual-discussion"], "action": "block" },
      { "name": "Sexual-assault images or video", "when": ["sexual-assault-media"], "action": "block" },
      { "name": "Adult content promotion", "when": ["sexual-adult-promotion"], "action": "block" }
    ]
  },
  "personal-information": {
    "action": "limit",
    "allowances": [],
    "restrictions": [
      { "name": "Other people's details", "when": ["personal-information-third-party"], "unless": ["personal-information-documentary"], "action": "block" }
    ]
  }
}

A copy keeps these settings when General changes. Check the preset changelog on the policy's page from time to time; see Preset versions and updates. To block insults aimed at a person as well, remove both Insults or humiliation rules from Harassment.

To block links to adult sites too, set their link safety action to block; General age-restricts them. See Link safety.

Keep limited content off profiles

CalmLens can't tell a public profile from a private chat: it decides from the content you send. Your app knows where the content is going, so your app decides where limited content appears. classification.moderation.flaggedCategories says why it was limited, such as sexual or personal-information.

StatusOn a profile, bio or anything other members browseIn a chat between members
allowedShow it.Deliver it.
limitedAsk the member to change it, and don't publish it.Deliver it, unless it opens the conversation; see Sexual openers.
age-restrictedDon't publish it.Deliver it only if your app allows this content in chat, and pass age confirmation for members who passed your check.
blocked or purgedDon't publish it. Tell the member why.Don't deliver it. Tell the sender why.

Age-restricted is still possible in this policy, because the copy keeps General's rules for other categories, such as graphic violence in images. If your profile photos go through an upload preset, you can give that preset its own stricter policy, so they are decided there without any check in your app.

Sexual openers

An unwanted, humiliating or coercive sexual advance aimed at someone is Sexual harassment under Harassment, and is blocked. Consensual sexual dialogue and sexual content not aimed at anyone are not. CalmLens reads what you send, so it can't know whether this recipient wants a message.

Two things help:

  • Send the conversation. Pass the sender and the earlier messages with each message, so it's read against what it answers, such as a repeated proposition after a refusal. See Threaded moderation.
  • Decide first messages in your app. Your app knows when a message opens a conversation. Hold a first message that is limited with sexual in flaggedCategories, and show it only if the recipient chooses to see it.

Adult communities without explicit images

Use the policy above with two changes, so explicit images stay out and text isn't treated differently by surface:

  • In Sexual, set the Text allowance's action to allow.
  • Keep Personal information as it is in General, with an action of allow and the restriction on other people's details.

Test the policy

Before assigning the policy to a live project, try representative profiles, messages and images on a test project, and check each row of the table above. See Testing.

Last updated

Signing in

Signing out

Cookies on CalmLens

We use essential cookies for sign-in and security. With your permission, functional cookies remember your preferences and Google Analytics measures website use and signups. Optional ad measurement cookies link Google ad clicks to signups. Personalised advertising stays off. Manage cookies