# `FaroEx.Audience`
[🔗](https://gitlab.com/estudio-yobo/faro/blob/v0.1.0/lib/faro_ex/audience.ex#L1)

Helpers that build the audience maps a Faro send accepts.

These return **plain maps in the wire shape** and validate nothing: the server's zod
schemas are the contract, and a second validator in Elixir would drift from them
silently. Use them to keep tag filters readable, not to police payloads.

    audience = %{
      "include" => [
        FaroEx.Audience.users(["42", "43"]),
        FaroEx.Audience.tag("plan", "pro")
      ]
    }

## Semantics worth knowing

Inside one selector, `deviceIds` and `externalUserIds` are *naming* fields and are
OR-ed together; `platforms` and `filters` are conditions and narrow that set with AND.
Include selectors are unioned, exclude selectors are subtracted afterwards, and an
empty `include` means "every subscribed device".

# `tag`

```elixir
@spec tag(String.t(), String.t() | atom()) :: map()
```

A selector filtered by one tag condition.

    FaroEx.Audience.tag("plan", "pro")                  # plan equals pro
    FaroEx.Audience.tag("plan", :not_equals, "pro")
    FaroEx.Audience.tag("country", :in, ["es", "mx"])
    FaroEx.Audience.tag("plan", :exists)

Only one condition per selector: to require two tags, put both filters in one
selector's `"filters"` list, or use two include selectors when either will do.

# `tag`

```elixir
@spec tag(String.t(), atom() | String.t(), term()) :: map()
```

# `users`

```elixir
@spec users([String.t()]) :: map()
```

A selector naming every device linked to these external user ids (max 1000).

An id nobody registered matches nothing; the send still succeeds with zero deliveries.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
