# Email Campaign Recommendation Attribution with the SDK

> Current Froomle documentation · [View canonical page](https://docs.froomle.com/froomle-doc-main/v2/js_lib/email-campaign-attribution.html)

<a id="EmailCampaignAttributionOverview"></a>

## Overview

Email campaign recommendation attribution lets the browser SDK send a `batch_click_on_recommendation` event when a user clicks a recommendation in an email campaign and lands on a website page that loads the SDK.

Use this feature when:

-   recommendations are generated for an email/newsletter campaign,
    
-   the email link points to the normal detail page for the clicked item,
    
-   the landing page loads the browser SDK,
    
-   you want the SDK to infer identity, consent state, device/user fields, and clicked item context from the landing page.
    

The feature only covers the click event after the browser lands on the site. It does not send `batch_open` or `batch_impression`, and it does not replace server-side/SFTP batch tracking for offline campaign workflows.

For the product-level batch event contract, see [Batch click on recommendation](https://docs.froomle.com/froomle-doc-main/v2/guide/topics/tracking-events.html#batch-click-on-recommendation).

<a id="EmailCampaignAttributionContract"></a>

## URL Payload Contract

The SDK supports these URL payload methods:

-   Selligent-friendly per-field parameters. Use this when the email platform can append and URL-encode individual values, but cannot easily build JSON or base64. Example: `[https://www.example.com/articles/123?froomle_email_campaign_id=spring-newsletter-2026-05-13&froomle_email_list_name=weekly_newsletter_recommendations&froomle_email_request_id=batch-request-12345](https://www.example.com/articles/123?froomle_email_campaign_id=spring-newsletter-2026-05-13&froomle_email_list_name=weekly_newsletter_recommendations&froomle_email_request_id=batch-request-12345)`
    
-   Per-field parameters with explicit item/channel overrides. Use this when the landing page context is not the clicked campaign item or the campaign should use a non-default channel. Example: `[https://www.example.com/articles/123?froomle_email_campaign_id=spring-newsletter-2026-05-13&froomle_email_list_name=weekly_newsletter_recommendations&froomle_email_request_id=batch-request-12345&froomle_email_action_item=123&froomle_email_action_item_type=article&froomle_email_channel=newsletter](https://www.example.com/articles/123?froomle_email_campaign_id=spring-newsletter-2026-05-13&froomle_email_list_name=weekly_newsletter_recommendations&froomle_email_request_id=batch-request-12345&froomle_email_action_item=123&froomle_email_action_item_type=article&froomle_email_channel=newsletter)`
    
-   Compact base64url JSON payload. Use this when a backend or custom link builder controls URL generation in code. Example: `[https://www.example.com/articles/123?froomle_email_reco=<base64url-json-payload>](https://www.example.com/articles/123?froomle_email_reco=%3Cbase64url-json-payload%3E);`
    
-   Compact URL-encoded raw JSON payload. This is accepted by the SDK for debugging and controlled generators, but base64url is preferred for production links because it avoids escaping issues. Example: `[https://www.example.com/articles/123?froomle_email_reco=%7B%22campaign_id%22%3A%22spring-newsletter-2026-05-13%22%2C%22list_name%22%3A%22weekly_newsletter_recommendations%22%2C%22request_id%22%3A%22batch-request-12345%22%7D](https://www.example.com/articles/123?froomle_email_reco=%7B%22campaign_id%22%3A%22spring-newsletter-2026-05-13%22%2C%22list_name%22%3A%22weekly_newsletter_recommendations%22%2C%22request_id%22%3A%22batch-request-12345%22%7D)`
    

For email platforms such as Selligent, prefer simple per-field URL parameters. This avoids JSON construction and base64 encoding inside the email template.

```text
froomle_email_campaign_id=spring-newsletter-2026-05-13
&froomle_email_list_name=weekly_newsletter_recommendations
&froomle_email_request_id=batch-request-12345
```

A complete landing URL can look like this:

```text
https://www.example.com/articles/123?froomle_email_campaign_id=spring-newsletter-2026-05-13&froomle_email_list_name=weekly_newsletter_recommendations&froomle_email_request_id=batch-request-12345
```

Required URL parameters:

| URL parameter | Event field | Meaning |
| --- | --- | --- |
| `froomle_email_campaign_id` | `campaign_id` | Campaign identifier for the batch/email campaign. |
| `froomle_email_list_name` | `list_name` | Recommendation list name used for the campaign recommendations. |
| `froomle_email_request_id` | `request_id` | Identifier of the generated recommendation batch/list result. This must match the batch recommendation output used to create the email links. |

Optional URL parameters:

| URL parameter | Event field | Default behavior |
| --- | --- | --- |
| `froomle_email_action_item` | `action_item` | Optional override for the clicked item id. If omitted, the SDK uses the landing page `context_item`. |
| `froomle_email_action_item_type` | `action_item_type` | Optional override for the clicked item type. If omitted, the SDK uses the landing page `context_item_type`; if that is missing, the SDK falls back to `article`. |
| `froomle_email_channel` | `channel` | Optional override for the event channel. If omitted, the SDK uses `email`. |

<a id="EmailCampaignAttributionSelligent"></a>

## Selligent-Style Template Setup

The SDK intentionally supports plain query parameters because Selligent-style templates commonly expose variables and URL helpers such as `urlencode(…​)`, `concat(…​)`, and tracking macros, but not necessarily a base64 encoder.

In that setup, build the link by appending the SDK parameters and URL-encoding each value:

```text
https://www.example.com/articles/123
?froomle_email_campaign_id=[% urlencode([VARIABLE.campaignId]) %]
&froomle_email_list_name=[% urlencode([VARIABLE.listName]) %]
&froomle_email_request_id=[% urlencode([VARIABLE.requestId]) %]
```

If your Selligent block already computes or appends other tracking parameters, keep those parameters as-is and add the Froomle parameters alongside them. The SDK only reads the `froomle_email_*` parameters and ignores unrelated campaign/ad-tracking parameters.

For most campaigns, keep the payload minimal and let the SDK infer `action_item` and `action_item_type` from the landing page. Use overrides only when the landing page context does not represent the clicked campaign item.

<a id="EmailCampaignAttributionCompactPayload"></a>

## Compact Payload Alternative

Backend-generated links can also use one compact payload parameter:

```text
froomle_email_reco=<base64url-json-payload>
```

The compact payload is a JSON object encoded as base64url:

```json
{
  "campaign_id": "spring-newsletter-2026-05-13",
  "list_name": "weekly_newsletter_recommendations",
  "request_id": "batch-request-12345"
}
```

```js
function encodeEmailAttributionPayload(payload) {
  return btoa(JSON.stringify(payload))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/g, '')
}

const payload = encodeEmailAttributionPayload({
  campaign_id: 'spring-newsletter-2026-05-13',
  list_name: 'weekly_newsletter_recommendations',
  request_id: 'batch-request-12345'
})

const href = `https://www.example.com/articles/123?froomle_email_reco=${payload}`
```

Use the compact payload when you control link generation in code. Use per-field `froomle_email_*` parameters when links are assembled in an email template tool.

`user_group` is not part of the SDK URL payload for this feature. The batch click event contract requires `campaign_id`, `list_name`, `request_id`, `action_item`, and `action_item_type`. If campaign-level benchmark attribution is needed in the future, document that contract explicitly before adding it to the SDK payload.

<a id="EmailCampaignAttributionEvent"></a>

## Event Sent by the SDK

When all required state is available and consent allows event tracking, the SDK sends:

```json
{
  "event_type": "batch_click_on_recommendation",
  "page_type": "email",
  "action_item": "123",
  "action_item_type": "article",
  "channel": "email",
  "list_name": "weekly_newsletter_recommendations",
  "request_id": "batch-request-12345",
  "campaign_id": "spring-newsletter-2026-05-13",
  "device_id": "...",
  "user_id": "..."
}
```

Notes:

-   `page_type` is `email` for this batch click event, separate from the normal landing page `detail_pageview`.
    
-   `device_id` and `user_id` follow the normal SDK identity and consent rules.
    
-   Consent level `0` blocks the batch click event.
    
-   Consent level `1` allows the event with anonymous identity, according to the normal SDK event policy.
    
-   Consent level `2` allows identified event tracking when a `user_id` is configured.
    

<a id="EmailCampaignAttributionTiming"></a>

## Timing and Deduplication

The SDK queues the email attribution payload until it has enough context to build a valid event.

The SDK waits for:

-   a valid per-field `froomle_email_*` payload, compact `froomle_email_reco` payload, or explicit helper call,
    
-   consent that allows event tracking,
    
-   `context_item` or an explicit `action_item`,
    
-   `context_item_type` or an explicit `action_item_type`.
    

This pending behavior is specific to email-link attribution. Ordinary recommendation impressions and clicks blocked at consent level `0` are not queued or replayed later. When consent becomes allowed, automatic DOM and React integrations observe the recommendation placements that are visible then as a new current exposure.

The SDK deduplicates the event within the current browser tab session. Repeated initialization, React StrictMode re-renders, or router calls with the same payload and landing context should still result in one `batch_click_on_recommendation` event.

<a id="EmailCampaignAttributionScriptTag"></a>

## Declarative DOM / Script-Tag

For script-tag integrations, no extra JavaScript call is needed. The SDK reads per-field `froomle_email_*` parameters or compact `froomle_email_reco` during initialization and sends the batch click event when page context is ready.

```html
<script
  src="https://cdn.example.com/froomle.global.js"
  data-froomle-env="production"
  data-froomle-page-visit="article_detail"
  data-froomle-context-item="123"
  data-froomle-context-item-type="article"
  data-froomle-user-id="user-456">
</script>
```

The email link should point to the detail page and include the required per-field `froomle_email_*` parameters, or the compact `froomle_email_reco` payload. The normal SDK page tracking can still send `detail_pageview` for the landing page; the email attribution event remains a separate `batch_click_on_recommendation` event with `page_type: "email"`.

<a id="EmailCampaignAttributionModule"></a>

## Module / JavaScript + DOM

For ES module DOM integrations, configure page context first, then call `init()`. The SDK processes the URL after `init()` resolves the DOM initialization path.

```ts
import {
  init,
  setConsent,
  setContextItem,
  setContextItemType,
  setEnvironment,
  setPageVisit,
  setUserId,
} from '@froomle/frontend-sdk'

setEnvironment('production')
setUserId('user-456')
setConsent(2)
setPageVisit('article_detail')
setContextItem('123')
setContextItemType('article')

await init()
```

If your route context is not ready at `init()` time, update `setContextItem(…​)` and `setContextItemType(…​)` when it becomes available. The queued email attribution payload is flushed once valid context exists.

<a id="EmailCampaignAttributionProgrammatic"></a>

## Programmatic JS/TS

Programmatic integrations can call the helper explicitly. This is useful when routing is fully application-owned or when you want to process a specific URL after navigation.

```ts
import {
  setContextItem,
  setContextItemType,
  setPageVisit,
  trackEmailCampaignRecommendationClickFromUrl,
} from '@froomle/frontend-sdk'

setPageVisit('article_detail')
setContextItem('123')
setContextItemType('article')

trackEmailCampaignRecommendationClickFromUrl(window.location.href)
```

You can also pass the payload directly:

```ts
import { trackEmailCampaignRecommendationClick } from '@froomle/frontend-sdk'

trackEmailCampaignRecommendationClick({
  campaign_id: 'spring-newsletter-2026-05-13',
  list_name: 'weekly_newsletter_recommendations',
  request_id: 'batch-request-12345'
})
```

Optional override example:

```ts
trackEmailCampaignRecommendationClick({
  campaign_id: 'spring-newsletter-2026-05-13',
  list_name: 'weekly_newsletter_recommendations',
  request_id: 'batch-request-12345',
  action_item: 'sku-987',
  action_item_type: 'product',
  channel: 'newsletter'
})
```

<a id="EmailCampaignAttributionReact"></a>

## React Bindings

`FroomleSdkInit` processes the URL during the SDK page-tracking flow. For regular page loads this is automatic.

For SPA route changes, call `trackEmailCampaignRecommendationClickFromUrl(…​)` after the route has updated the SDK page context. Repeated calls are deduplicated for the same tab/session payload.

```tsx
import {
  setContextItem,
  setContextItemType,
  setPageVisit,
  trackEmailCampaignRecommendationClickFromUrl,
} from '@froomle/frontend-sdk'

function onArticleRoute(article) {
  setPageVisit('article_detail')
  setContextItem(article.id)
  setContextItemType('article')

  trackEmailCampaignRecommendationClickFromUrl(window.location.href)
}
```

<a id="EmailCampaignAttributionUnsupported"></a>

## Unsupported Integration Shapes

The SDK feature requires browser SDK state. It is not available for pure no-SDK/manual integrations where the page does not load `@froomle/frontend-sdk`.

For no-SDK/manual integrations, follow [Manual Event Integration](https://docs.froomle.com/froomle-doc-main/v2/guide/manual-integration/events.html) and the [batch click contract](https://docs.froomle.com/froomle-doc-main/v2/guide/topics/tracking-events.html#batch-click-on-recommendation). Your implementation must own consent enforcement, identity handling, event validation, retries, and deduplication.

<a id="EmailCampaignAttributionDiagnostics"></a>

## Diagnostics

The browser runtime exposes support diagnostics at:

```js
window.FroomleFrontendSdkRuntime.diagnostics.emailCampaignAttribution
```

Useful fields include:

| Field | Meaning |
| --- | --- |
| `status` | Current state, for example `idle`, `detected`, `pending`, `blocked`, `invalid`, `dispatching`, `dispatched`, `error`, or `duplicate`. |
| `source` | Where the attribution came from: `url:params` for per-field URL parameters, `url:compact` for `froomle_email_reco`, or `programmatic` for helper calls. |
| `detectedAt` | Timestamp when the SDK detected a URL/helper payload. |
| `paramNames` | URL parameter names the SDK associated with the detected payload. This helps verify whether the SDK used Selligent-style per-field parameters or the compact payload. |
| `cleanUrl` | Whether the SDK should remove attribution parameters from the browser URL after dispatch. Automatic SDK URL processing leaves this `false`; explicit helper calls can opt into cleanup. |
| `landingUrlWithoutAttributionParams` | Landing URL after removing known Froomle email attribution parameters. This helps compare repeated links without exposing the `froomle_email_*` payload in diagnostics. |
| `payload` | Normalized payload after parsing and alias handling. |
| `validationErrors` | Missing or invalid fields, for example `missing list_name`. |
| `blockedReason` | Why the event is not sent yet, such as `consent` or `context-not-ready`. |
| `duplicate` | `true` when the SDK suppresses a repeated event for the same tab/session payload. |
| `dedupeKey` | Internal deduplication key for support debugging. It combines campaign/list/request/item context and the landing URL without attribution parameters. |
| `dispatchedAt` | Timestamp of the most recent successful dispatch. |

Use the diagnostics object together with the Froomle Diagnostics Overlay when validating campaign links in a browser.
