> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Track topic interest for smarter targeting

> Tag users based on the pages they visit and the page they subscribe to push notifications from, then segment for targeted campaigns.

You can tag users in OneSignal based on the pages they interact with on your site or app, then segment those tags for targeted messaging. This page covers two distinct patterns — pick the one that matches your goal, or run both side by side.

## Choose your pattern

| Pattern                                                       | When the code runs                | What it sets                                      | Platforms         |
| ------------------------------------------------------------- | --------------------------------- | ------------------------------------------------- | ----------------- |
| [Tag by page topic](#tag-by-page-topic-every-visit)           | On every page or screen visit     | A `cat_<category>` opt-in Tag set to `"1"`        | Web, Android, iOS |
| [Tag at subscription](#tag-at-subscription-one-time-web-only) | Once, when a user opts in to push | An attribution tag (`subscription_page = gaming`) | Web only          |

**Tag by page topic** uses the [`cat_*` Tag convention](./permission-requests#categories) to build a category-interest profile from browsing behavior. The same `cat_<category>` Tags that a [Category Prompt](./permission-requests#categories) sets explicitly can be filled in automatically as readers browse — so a single segment like `cat_sports = "1"` matches both audiences.

**Tag at subscription** captures a single point-in-time signal at opt-in — useful for source-aware welcome messaging and drip campaigns where the page a user subscribed from predicts what they want to read next.

## Prerequisites

* OneSignal [Web SDK](./web-sdk-setup) and/or [Mobile SDK](./mobile-sdk-setup) installed and initialized.
* Familiarity with [Tags](./add-user-data-tags) and [Segments](./segmentation).

***

## Tag by page topic (every visit)

Tag users with the categories they engage with most so you can deliver more personalized messaging — boosting relevance, click-through, and satisfaction.

This pattern uses the `cat_<category>` Tag convention — the same Tag namespace populated by the [Category Prompt](./permission-requests#categories) and by [preference centers](./preference-center). Auto-tagging from page visits and explicit opt-ins from prompts coexist in the same Tags, so a single segment like `cat_sports = "1"` matches both audiences.

Example use cases:

* On a fashion site, a user is only interested in men's shoes — not women's dresses.
* On a news app, a user consistently visits finance and sports articles — but never entertainment or politics.

### 1. Define your category taxonomy

Start by identifying the content categories you want to track. These might be:

* Broad verticals like `sports`, `finance`, or `entertainment`
* Product types like `apparel`, `home`, or `beauty`
* Authors or brands

The category name becomes the suffix on the `cat_*` Tag — for example, the `sports` category produces a `cat_sports` Tag.

<Note>
  * Start with 3–8 categories to keep management simple.
  * Stay under 20 categories overall to avoid bloat.
  * Use lowercase, underscored category names so they match the Tag Key convention everywhere they appear (`cat_breaking_news`, not `cat_BreakingNews`).
</Note>

### 2. Add code to track category visits

Set `cat_<category> = "1"` whenever a reader views a page or screen in that category. The Tag is idempotent — repeated calls with the same value are a no-op — so you can call this on every page load.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const categories = ["sports", "entertainment"]; // One or many

  categories.forEach(category => {
    OneSignal.User.addTag(`cat_${category}`, "1");
  });
  ```

  ```kotlin Kotlin theme={null}
  val categories = listOf("sports", "entertainment") // One or many

  categories.forEach { category ->
      OneSignal.User.addTag("cat_$category", "1")
  }
  ```

  ```swift Swift theme={null}
  let categories = ["sports", "entertainment"] // One or many

  for category in categories {
      OneSignal.User.addTag(key: "cat_\(category)", value: "1")
  }
  ```
</CodeGroup>

<Warning>
  If you also use the [Category Prompt](./permission-requests#categories) to capture explicit opt-ins, respect the user's choice. A `cat_<category> = "0"` value means the reader explicitly opted out — overwriting it with `"1"` from browsing behavior breaks their preference. Gate your `addTag` call on the existing Tag value, or skip the auto-tag for users who have already seen the Category Prompt.
</Warning>

### 3. Segment and send personalized messages

Once Tags are applied, you can target users with:

* [Segments](./segmentation) to build rule-based groups.
* [API filters](/reference/create-message#filters) to dynamically include users in a single campaign.

Common segmentation patterns:

* **Any engagement** with a category: `cat_sports exists`. Matches both explicit opt-ins and auto-tagged readers, regardless of value.
* **Active interest** in a category: `cat_sports = "1"`. Includes the auto-tagged readers above the threshold and the prompt opt-ins.
* **Multi-category** targeting: `cat_sports = "1" OR cat_finance = "1"`.
* **Excluded categories**: `cat_politics != "1"` to suppress readers who opted out.

Example use cases:

* Send breaking news alerts to readers with `cat_breaking_news = "1"`.
* Promote a finance newsletter to readers with `cat_finance = "1"` who do not have `nl_morning_briefing = "1"`.
* Send Black Friday deals to shoppers with `cat_apparel = "1"`.

### Best practices

Do:

* Use the `cat_<category>` Tag Key convention consistently across the Category Prompt, preference centers, and this auto-tag pattern. A single Tag namespace makes segmentation predictable.
* Test your tag logic with `console.log()` (web) or your platform's logger before launching campaigns.
* Keep the category list in a central place (a config file or remote config) so you can adjust without touching every page.

Avoid:

* Long or overly specific tag keys (full article titles, long URLs).
* Exceeding OneSignal's [tag limits](https://onesignal.com/pricing).
* Tagging with personally identifiable information (PII).
* Overwriting an explicit `cat_<category> = "0"` opt-out with an auto-tagged `"1"`.

***

## Tag at subscription (one-time, web only)

Tag web push subscribers with contextual data — such as the page topic or URL path they subscribed from — to deliver targeted follow-up campaigns. This pattern detects the opt-in, applies tags, and feeds segments for drip-style messaging.

### 1. Tag users on opt-in

When a user subscribes to push notifications, use the [`PushSubscription` change listener](./web-sdk-reference#addeventlistener-push-subscription-changes) to detect the opt-in and apply tags with contextual data about the page they were viewing.

```javascript theme={null}
function pushSubscriptionChangeListener(event) {
  if (event.current.optedIn && !event.previous.optedIn) {
    // User just opted in — tag with subscription context
    var pathSegment = window.location.pathname.split('/')[1] || 'home';
    var pageTopic = document.querySelector('meta[name="article-topic"]')?.content || 'general';

    OneSignal.User.addTags({
      subscription_page: pathSegment,
      subscription_page_topic: pageTopic,
    });
  }
}

OneSignalDeferred.push(function(OneSignal) {
  OneSignal.User.PushSubscription.addEventListener("change", pushSubscriptionChangeListener);
});
```

**How this works:**

* The `change` event fires whenever the user's push subscription state changes (opt-in, opt-out, token refresh).
* `event.current.optedIn` is `true` when the user has an active subscription. Checking `!event.previous.optedIn` ensures tags are only applied on the initial opt-in, not on every state change.
* `window.location.pathname.split('/')[1]` captures the first path segment as the subscription context. For example, if the URL is `https://example.com/gaming/article-123`, the `subscription_page` tag is set to `gaming`.
* `pageTopic` is extracted from a `<meta>` tag, falling back to `'general'`. Adjust this to match your site's metadata structure.

### 2. Segment users by tag

Once tags are applied, use [Segments](./segmentation) or [API filters](/reference/create-message#filters) to target users based on those tags. For example:

* Send a campaign to users where `subscription_page` is `gaming`.
* Create dynamic segments based on tag values and timing (for example, hours since first session).

### 3. Automate follow-up messaging

Build drip-style campaigns that trigger messages based on when the user subscribed and what content they subscribed under.

**Example: Drip campaign for gaming subscribers**

| Segment name | Filters                                                           | Description                              |
| ------------ | ----------------------------------------------------------------- | ---------------------------------------- |
| Gaming 1     | `subscription_page` = `gaming` AND First Session > 2h AND \< 24h  | Reach out 2–24 hours after subscription. |
| Gaming 2     | `subscription_page` = `gaming` AND First Session > 24h AND \< 48h | Follow up 1 day later.                   |
| Gaming 3     | `subscription_page` = `gaming` AND First Session > 72h AND \< 96h | Final check-in after 3 days.             |

<Info>
  Use upper time limits (`<`) to prevent users from lingering in segments once the messaging window has passed.
</Info>

### 4. Combine segments with message templates

Once segments are created:

* Build [Templates](./templates) for each stage in the campaign (intro, reminder, promo).
* Use [Journeys](./journeys-overview) to send these messages when users enter the appropriate segment.

Example message ideas:

* Invite to a gaming community or social group.
* Recommend trending articles related to their topic.
* Send an exclusive offer or discount code.

### Best practices

* Use meaningful tag names and values that reflect actual user intent.
* Extract tag values dynamically from page metadata when possible.
* Only tag on the initial opt-in — the listener above checks `!event.previous.optedIn` to avoid re-tagging on every state change.

<Warning>
  Do not include personally identifiable information (PII) such as names or email addresses in tag values. Avoid hardcoding tag values across your entire site — extract them dynamically from page context.
</Warning>

***

## FAQ

### When should I use one pattern versus the other?

Use **tag by page topic** to build a behavioral interest profile over time. The counter grows with every visit, so segments can be tuned by engagement depth (`gaming >= 5`). Use **tag at subscription** to capture a single point-in-time attribution at opt-in, useful for source-aware welcome messaging where you want to react to *where* the user subscribed before they have a long visit history. Both patterns can run side by side on the same site — they set different tags and answer different questions.

### Do tags persist if the user clears browser data?

No. Clearing browser data on web creates a new Subscription, and the per-topic counters stored in `localStorage` reset along with it. If the user re-subscribes (manually or via [auto-resubscribe](./web-push-setup#auto-resubscribe)), the `change` listener fires again and re-applies the subscription tag based on the current page, but the visit counters start fresh.

### Can I update tags after the initial subscription?

Yes. You can call `OneSignal.User.addTag()` or `OneSignal.User.addTags()` at any time to add or update tags. The subscription listener is useful for the initial context, but you can also tag users based on ongoing behavior.

### Should I use these patterns instead of message event filters?

They serve different purposes. Use the patterns on this page when you want to segment by **which pages a user visited or subscribed from** — that is, signal that originates on your site or app. Use [Message event filters](./segmentation#message-event-filters) when you want to segment by **which OneSignal messages a user has interacted with** (delivered, clicked, etc.). They are complementary, not redundant.

### Can I only tag readers who show repeated engagement, or use counter values for engagement depth?

Yes — both variants layer on top of the same `cat_*` namespace by tracking a per-category visit counter in `localStorage` (web), `SharedPreferences` (Android), or `UserDefaults` (iOS):

* **Threshold (binary).** Increment the local counter on every visit, but only call `OneSignal.User.addTag("cat_<category>", "1")` once the counter reaches your threshold (for example, `3` visits). The Tag stays binary and combines cleanly with the [Category Prompt](./permission-requests#categories) — only engaged readers get tagged.
* **Counter values.** Call `OneSignal.User.addTag("cat_<category>", visits.toString())` every visit. You can then segment with `cat_sports >= "5"` for engagement-depth targeting. The trade-off is that you can no longer combine these auto-tagged values with the binary `"0"` / `"1"` opt-in scheme used by the Category Prompt — pick one scheme per category and use it consistently.

### Does the subscription-source pattern work on mobile?

Not directly. The `PushSubscription.addEventListener("change", ...)` API is web-specific. On iOS and Android, you can achieve a similar attribution by calling `addTag` from inside your opt-in flow — for example, immediately after the user accepts a [permission prompt](./permission-requests), tag them with the screen or feature they were on.

***

## Related pages

<Columns cols={2}>
  <Card title="Tags" icon="tags" href="./add-user-data-tags">
    Add custom properties to users for personalization and segmentation.
  </Card>

  <Card title="Segments" icon="users" href="./segmentation">
    Group users by properties, tags, and behavior for targeted messaging.
  </Card>

  <Card title="Web SDK reference" icon="code" href="./web-sdk-reference">
    Full reference for the OneSignal Web SDK including subscription listeners and tagging methods.
  </Card>

  <Card title="Mobile SDK reference" icon="mobile" href="./mobile-sdk-reference">
    Full reference for the OneSignal Mobile SDK including tagging methods.
  </Card>

  <Card title="Journeys" icon="route" href="./journeys-overview">
    Build multi-step messaging workflows triggered by segment entry or custom events.
  </Card>
</Columns>
