# Web Pixel Events

Zigpoll's Shopify checkout extension publishes a documented set of [Web Pixels custom events](https://shopify.dev/docs/api/web-pixels-api/emitting-data) so you can react to survey activity from a Shopify Custom Pixel — fire a Klaviyo flow when a survey completes, push answers into GA4 / GTM, kick off a loyalty action when a question is answered, etc.

All events use the `zigpoll:` namespace and fire from the Zigpoll post-purchase / order-status / customer-account surfaces.

{% hint style="info" %}
If you're only after a quick GA4 setup, the simpler [GA4 Shopify Pixel](/integrations/ga4-shopify-pixel.md) recipe uses the legacy `zigpoll-event` channel and is easier to copy-paste. This page is the full event reference for richer integrations.
{% endhint %}

### Event catalog

| Event                      | When it fires                                                                                                                                                                                                                                  |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `zigpoll:poll_rendered`    | The first time a survey's frame is shown to the shopper on this surface                                                                                                                                                                        |
| `zigpoll:poll_opened`      | The survey widget expands / becomes interactive                                                                                                                                                                                                |
| `zigpoll:slide_viewed`     | A new slide becomes the active slide                                                                                                                                                                                                           |
| `zigpoll:answer_submitted` | Any answer is accepted by the server — fires once per submitted slide, for every interactive slide type (single-choice, multi-choice, dropdown, rating, satisfaction, NPS, range, free-response, form, email-capture, rank, date, file-upload) |
| `zigpoll:poll_completed`   | All required slides have been answered. Payload includes an `answers` array with every collected response                                                                                                                                      |
| `zigpoll:poll_closed`      | The shopper dismisses the widget without completing                                                                                                                                                                                            |
| `zigpoll:poll_hidden`      | The widget is hidden permanently (`hideAfterSubmission` / `hideAfterClose`)                                                                                                                                                                    |

### Base payload

Every `zigpoll:*` event includes these fields on `event.customData`:

| Field               | Type                | Description                                                                                    |
| ------------------- | ------------------- | ---------------------------------------------------------------------------------------------- |
| `pollId`            | string              | Internal survey id                                                                             |
| `pollHandle`        | string              | Slugified survey title                                                                         |
| `pollTitle`         | string              | Survey title                                                                                   |
| `surface`           | string              | `shopify_checkout`, `shopify_thank_you`, `shopify_order_status`, or `shopify_customer_profile` |
| `shopifyOrderId`    | string \| undefined | The Shopify order id when available                                                            |
| `shopifyCustomerId` | string \| undefined | The Shopify customer id when available                                                         |
| `myshopifyDomain`   | string              | The store's `.myshopify.com` domain                                                            |
| `timestamp`         | string              | ISO-8601 timestamp of the event                                                                |

### Answer payload (`zigpoll:answer_submitted` and entries in `zigpoll:poll_completed.answers[]`)

Per-slide answer entries match the shape Zigpoll uses everywhere else — webhooks, mailer, Klaviyo bridge:

| Field        | Type                   | Description                                                                                 |
| ------------ | ---------------------- | ------------------------------------------------------------------------------------------- |
| `key`        | string                 | The slide's handle (the identifier you set in the survey editor)                            |
| `value`      | string \| number       | Compiled human-readable answer. Joined with `,` for multi-answer types                      |
| `arrayValue` | string\[] \| undefined | Present for multi-answer slides (multi-choice, rank, form) — the answer choices as an array |
| `slideId`    | string                 | Internal slide id                                                                           |

#### How `value` is shaped per slide type

| Slide type                                     | Example `value`                           | `arrayValue`        |
| ---------------------------------------------- | ----------------------------------------- | ------------------- |
| `single-choice`, `dropdown`                    | `"Blue"`                                  | —                   |
| `multi-choice`                                 | `"Blue, Green"`                           | `["Blue", "Green"]` |
| `rank`                                         | `"#1 Apple, #2 Pear"`                     | —                   |
| `rating`, `satisfaction`, `nps`, `range`       | `4`                                       | —                   |
| `free-response`, `short-answer`, `long-answer` | `"I like the ocean"`                      | —                   |
| `email-capture`                                | `"alice@example.com"`                     | —                   |
| `form`                                         | `"Name: Alice, Email: alice@example.com"` | —                   |
| `date`                                         | `"03/15/2026"`                            | —                   |
| `file-upload`                                  | `"https://…/file1, https://…/file2"`      | —                   |

### Subscribing from a Custom Pixel

1. Go to your **Shopify Dashboard → Settings → Customer Events**.
2. Click **Add custom pixel**.
3. Paste a subscription block like the one below:

```javascript
analytics.subscribe('zigpoll:answer_submitted', (event) => {
  const { key, value, arrayValue, slideId, pollId, surface, shopifyOrderId } = event.customData;

  // `value` is the compiled answer (string or number).
  // `arrayValue` is populated for multi-choice / rank / form.
  console.log(`Survey ${pollId} - ${key}: ${value}`);
});

analytics.subscribe('zigpoll:poll_completed', (event) => {
  const { pollId, answers, shopifyOrderId } = event.customData;

  // answers is an array of {key, value, arrayValue, slideId} entries
  answers.forEach(({ key, value }) => {
    console.log(`${key}: ${value}`);
  });
});
```

### Forwarding to GA4 with the new events

If you want richer GA4 events than the legacy [GA4 Shopify Pixel](/integrations/ga4-shopify-pixel.md) recipe gives you — for example, separate events for `Survey Started`, `Question Answered`, and `Survey Completed` — replace the legacy subscription with one block per event:

```javascript
var f = document.getElementsByTagName('script')[0];
var j = document.createElement('script');
j.async = true;
j.src='https://www.googletagmanager.com/gtag/js?id=G-XXXX';
f.parentNode.insertBefore(j, f);

window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXX');

analytics.subscribe('zigpoll:answer_submitted', (event) => {
  const { key, value, pollId, pollTitle } = event.customData;
  gtag('event', 'zigpoll_answer_submitted', {
    event_category: 'Zigpoll',
    event_label: pollTitle,
    zigpoll_poll_id: pollId,
    zigpoll_question: key,
    zigpoll_response: value
  });
});

analytics.subscribe('zigpoll:poll_completed', (event) => {
  const { pollId, pollTitle, answers } = event.customData;
  gtag('event', 'zigpoll_poll_completed', {
    event_category: 'Zigpoll',
    event_label: pollTitle,
    zigpoll_poll_id: pollId,
    zigpoll_answer_count: answers.length
  });
});
```

### Security note

Per Shopify's own [Web Pixels docs](https://shopify.dev/docs/api/web-pixels-api/emitting-data#publishing-custom-events), custom events can be published by anyone with browser-console access — including the shopper. Treat the payloads as untrusted input for security-sensitive decisions; they're fine for analytics, attribution, and triggering downstream marketing flows, but don't grant rewards or change account state purely based on a `customData` value.

### Backward compatibility

The original `zigpoll-event` channel that the [GA4 Shopify Pixel](/integrations/ga4-shopify-pixel.md) recipe subscribes to is still published unchanged. Existing pixels keep working — these new namespaced events are additive.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zigpoll.com/shopify-app/shopify-web-pixel-events.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
