Skip to content

Privacy policy

Last updated: 2026-09-11. Version 2.2.

This policy explains what data the VIBE Search and Discovery Shopify app (“VIBE”, “the app”, “we”, “us”) collects, how we use it, who we share it with, how long we keep it, and the rights available to merchants and their customers.

It applies to the app as installed by a Shopify merchant on their store and to the storefront search experience the app provides to that store’s shoppers.

VIBE Search & Discovery is operated by the VIBE/coi team. Privacy questions and requests can be sent to support@coi.se.

Related pages: Terms of Use, Sub-processors and Data retention.

  • The merchant (the Shopify store owner who installs VIBE) is the data controller for their store and customer data.
  • VIBE acts as a data processor for store and shopper data, processing it on the merchant’s behalf and instructions to provide search and discovery. VIBE determines the purposes of its own merchant account administration, billing, support and service-security records.
  • Shopify is the underlying platform and the merchant’s primary service provider. VIBE receives data from Shopify under the merchant’s authorization (the access scopes granted at install).

This policy describes the data practices of the live service.

When you install VIBE, you grant the app a defined set of access scopes. VIBE requests only the following scopes and uses each for the stated purpose.

ScopeWhat it allowsWhy VIBE uses it
read_companiesRead Shopify B2B company relationshipsChecks that a signed-in customer belongs to the selected company location before returning its permitted products and prices
read_localesRead shop languagesDetects the store’s enabled languages so search works in the shopper’s language
read_marketsRead shop marketsDetects enabled markets for correct per-market product and price handling
read_ordersRead ordersReceives paid-order, refund, and cancellation notifications so sales can be connected to earlier search activity and adjusted in your analytics. See Order data below
read_productsRead product catalogBuilds VIBE’s copy of your catalog (titles, descriptions, options, images, metafields) for search
read_publicationsRead publication and channel dataDetermines which products and collections are published to the online store
read_themesRead theme filesAnalyzes your theme so the search widget and product cards match it
unauthenticated_read_product_listingsStorefront read of published listingsLets VIBE create and use a Storefront API access token to read your Search & Discovery filters
write_themesWrite theme filesInstalls VIBE’s helper files into your theme. See Theme access below

Collections. VIBE does not request a read_collections scope. Collection data is derived from read_products and read_publications, and the app subscribes to collections/create, collections/update, and collections/delete webhooks to keep its copy current.

Through these scopes and webhooks, the app processes:

  • Product catalog data: product titles, descriptions, options and variants, images, tags, category, vendor, collections, prices, availability, markets, and selected metafields, used to build VIBE’s copy of your catalog and the search index.
  • Theme data: files of the theme being analyzed (Liquid sections, snippets, blocks, templates, and JavaScript assets), read to find the theme’s search surfaces and product card. Theme analysis runs during setup, when you start it from the app, and again when you publish a different theme.
  • Markets and locales: to serve search in the correct language and market.
  • B2B buyer context: Shopify customer, company and company-location identifiers and customer-to-location role assignments, used to authorize company-specific product eligibility and prices. Names, contact details and postal addresses are not requested by these checks.
  • Storefront filters: the Search & Discovery filters configured for your store, read through the Storefront API.

VIBE writes two files into the theme it analyzes, which is your published theme unless you selected another theme during setup, so product cards in search results render through your theme’s own card template:

  • sections/vibe-card.liquid, a helper section installed on every theme analysis.
  • snippets/vibe-quick-card.liquid, a helper snippet installed only on themes whose quick search renders product cards inline rather than through a snippet.

These are the only theme files VIBE writes. Both are rewritten on each analysis so they stay in step with your theme. VIBE reads theme files to analyze the theme. It does not modify any other theme file.

If the app has been granted access to order data for your store, Shopify notifies VIBE when an order is paid, refunded, or cancelled. VIBE uses paid-order notifications only to connect orders carrying the VIBE cart attribute described in section 4 to earlier search activity. Refund and cancellation notifications are used only to correct previously attributed analytics.

On a matching search event, VIBE stores the Shopify order id, attributed product id, original and current attributed revenue, and a label describing how the match was made (cart add or click). For refund and cancellation replay, VIBE keeps a minimal lifecycle record containing the webhook delivery id, order id, event type, refunded product ids and amounts, and whether the order matched VIBE attribution. An unmatched record is kept for 48 hours to cover a refund or cancellation arriving just before its paid-order attribution; it is then deleted. A matched record is deleted 90 days after creation. Refund and cancellation corrections can be applied only while the matching search event remains within its 90-day retention period. Legacy control-group attribution created before line-level product ids were stored cannot be matched safely to a refunded product line unless an attributed product id was already recorded. The rest of each notification, including the customer’s name, email, address, and payment details, is processed in memory and never stored. Product ids from a paid order are held for 60 seconds in a cache so stock notifications caused by the order are handled correctly. The matching itself runs as a background job that holds the order id, product ids, prices, quantities, the order/admission timestamp, and the cart attribute. The job becomes eligible for removal 24 hours after it completes or 7 days after it fails. An independent cleanup runs every 15 minutes, including when no further orders arrive; queue count limits may remove it earlier. Waiting and retrying jobs remain until processing finishes or the store is deleted. Service outages can delay processing and cleanup.

Because VIBE holds read_orders, the app is subject to Shopify’s Protected Customer Data requirements. VIBE’s data-use declarations are submitted to Shopify separately from this policy.

To operate the service for your store, VIBE stores:

  • Shop configuration: store domain, plan, app settings, widget configuration, Explore controls, result rules, exclusion rules, search configuration, and usage limits.
  • Billing and usage state: plan, monthly visit and search counts, overage state, and monthly billing records used for usage-based charging through Shopify.
  • Access tokens: your Shopify access tokens, session refresh tokens and, where used, a Storefront API access token. They are encrypted at rest (see section 8).
  • Shopify admin sessions: the session records Shopify’s app framework requires. Online sessions include the staff member’s Shopify user id, name, and email.
  • Merchant email address: taken from your Shopify shop details, with the Shopify session email as a fallback, and used only to send operational email about your own account (see section 5). VIBE keeps a delivery record for each email (recipient, subject, status).
  • Storefront password: if your online store is password protected and you enter the password during setup, VIBE stores it encrypted and uses it only to render product cards from your storefront. A storefront session cookie obtained with it is cached for up to 23 hours.
  • Verified store owner record: when the store owner opens the app, VIBE stores the owner’s Shopify user id and encrypted email so it can notify the owner when a customer data request result is ready.
  • Trial record: the store domain and the date of the first trial, kept so a free trial is not granted twice.

4. Data we collect from store visitors (shoppers)

Section titled “4. Data we collect from store visitors (shoppers)”

VIBE does not build shopper profiles containing names, email addresses or postal addresses. It processes the identifiers and activity below, including signed-in customer and company-location identifiers needed for B2B access and pricing. Some of this is essential to run the service. The rest is optional and depends on the consent choices the shopper makes through your store’s cookie banner, which VIBE reads through Shopify’s Customer Privacy API.

When the search widget loads, it creates a random visit identifier and stores it in the browser’s sessionStorage. The identifier expires after 30 minutes of inactivity and does not survive the browser tab. It is sent with each search request and used to:

  • count visits toward your plan allowance,
  • deliver results and keep suggestions consistent within a visit, and
  • keep a shopper in the same group during an A/B test.

To count a visit only once across server restarts, VIBE stores a store-specific hash of the visit identifier with its start and last-activity times. It does not store the raw identifier in this essential billing record. An hourly job removes these records after 24 hours without activity. Monthly billing totals contain no visit identifiers. If browser storage is unavailable, search still works but the visit cannot be counted.

Every search request reaches VIBE through Shopify’s App Proxy with the shopper’s IP address. VIBE uses the IP address for abuse protection: a per-minute request limit per IP, and a daily cap on how many new billable visits one IP can start. These counters live in a short-lived store and expire on their own (per-minute counters after about one minute, the daily cap after 24 hours). The IP address is not written to VIBE’s database. It can appear, together with the request URL, in short-lived server request logs used for operations and troubleshooting. The browser’s user-agent string is checked to skip known bots and is not stored.

Essential: signed-in buyers and B2B pricing

Section titled “Essential: signed-in buyers and B2B pricing”

Shopify supplies the signed-in customer identifier in its verified App Proxy request. For B2B requests, VIBE also receives the selected company-location identifier and checks company membership through Shopify before returning that location’s eligible products and prices. VIBE uses country and currency to select the correct presentment price.

These checks are necessary to deliver authorized storefront results and are separate from optional analytics. Raw customer and company-location identifiers are processed in memory and exchanged with Shopify; the authorization and price caches use store-specific keyed hashes for buyer or location partitions. Authorization decisions, product eligibility and exact contextual prices have a hard 60-second cache lifetime. This context is not sent to the VIBE AI API or Anthropic. Request URLs may appear in operational request logs as described above.

Search events are stored only when Shopify’s Customer Privacy API reports that the shopper allows analytics. Each event may include:

  • the visit identifier,
  • the search text,
  • the number of results and which products were returned,
  • the clicked product, its rank position, and time to click,
  • cart adds made from results,
  • filters applied and Explore control values,
  • which result rules matched,
  • the A/B test group,
  • the storefront surface the request came from, and
  • response time.

VIBE also records product impressions: which products were shown for a search, in what position, and for how long. Search Preview inside the app is excluded from shopper analytics.

For each consented search event, VIBE assigns a random event id and event time before attempting the direct database write. If that write fails or exceeds its short latency budget, a recovery job can temporarily hold the exact same event id and time, pseudonymous visit identifier, source surface and A/B group, raw search text, result count and response time, semantic and Explore controls, filters, matched rules, and returned product and variant ids with their positions. This does not introduce an additional data category; it is a delivery copy of the event described above. The job is tried up to 12 times with 60-second exponential backoff (about 34 hours to the last scheduled attempt) and is deleted immediately after success or after the final failed attempt, including exhausted failures.

Search text is stored on search events for 90 days and in aggregated daily reports (top searches, searches with no results) for 3 years. Search text is not on the list of fields that VIBE masks in application logs, but the application does not intentionally write shopper search text to its logs.

When the shopper allows both analytics and marketing, VIBE stores a random attribution identifier in the browser’s localStorage as vibe_aid, records it on click and cart-add events, and asks Shopify to carry it in the cart as the private cart attribute __vibe_aid. It also keeps a short record of the last clicked product in sessionStorage. If the app has access to order data, this identifier is what connects a paid order to the earlier search activity (see Order data in section 2). It contains no personal details, but it can link one browser’s activity to an order, so include it in your privacy review.

If you turn on Google Tag Manager events in VIBE, and the shopper allows analytics, marketing, and sale of data, the widget pushes vibe_search, vibe_search_no_results, and vibe_search_click events to the page’s dataLayer. The payload can include the search text, result count, response time, product handle, and product position. This is off by default. Any further handling by GTM and the tags you load is governed by your own configuration and Google’s terms, not by VIBE.

Consent changes take effect for later requests. When a shopper withdraws consent, the widget stops the optional processing above, removes vibe_aid from localStorage, clears the last-click record, and asks Shopify to remove the cart attribute.

  • Visual search. If a shopper uploads an image to search by picture, the image is sent to the VIBE AI API to compute a numeric representation. The Shopify app handles the upload in memory and does not write the uploaded image to its database, cache or job queues. Processing by the AI service is described on the Sub-processors page.
  • Your Vibe. Products a shopper saves are kept in that shopper’s own browser (localStorage, per store). When the shopper opens Your Vibe, the saved product references are sent to VIBE to build recommendations. The titles, vendors, and types of the saved products are sent to Anthropic’s Claude to name the recommendation groups. No visit identifier, attribution identifier, or other shopper identifier is sent with them. When an internal recommendation request is not restricted to a market, VIBE may cache the generated groups, source-product references and recommended products for six hours, keyed by the store and a hash of the saved product references. Market-specific storefront requests bypass this cache.
  • Search text embeddings. VIBE caches the numeric representation of a search phrase for up to one year under a hash of the phrase, so repeated searches are faster. The cache holds the numbers, not the phrase and not who searched.

Whether your store needs a consent banner is your decision as the controller. VIBE follows the answer Shopify’s Customer Privacy API gives for each shopper.

VIBE uses the data above only to provide and operate the service:

  • Search and discovery: generate numeric representations of products and search text to serve meaning-based search, suggestions, Explore, visual search, and Your Vibe.
  • Search configuration: analyze a sample of your catalog to decide which product fields carry searchable meaning (see Anthropic in section 6).
  • Analytics: aggregate search events into daily reports (total searches, unique visits, no-result rate, clicks, cart adds, conversions, and revenue attributed to VIBE activity) shown in your dashboard.
  • Usage-based billing: count visits and searches to apply plan limits and overage charges through Shopify.
  • Operational merchant email: messages about your own account, including install and uninstall confirmations, a welcome message when search goes live, usage warnings, limit and overage alerts, inactivity alerts, weekly and monthly summaries, a request for an App Store review, and a notification when a customer data request result is ready.

VIBE does not sell data and does not use shopper data for advertising.

VIBE relies on the third-party providers below to deliver the service. The current list, with the data shared with each provider and how each is engaged, is kept on the Sub-processors page.

Sub-processorPurposeData shared
ShopifyUnderlying platform; source of catalog, theme, order, market, locale, and session data; billingPlatform-level merchant and order data under your authorization
VIBE AI APIGenerates numeric representations of products and search text, translation, and Explore suggestionsProduct text and images, search text with a target language, images a shopper uploads for visual search, references to products a shopper saved in Your Vibe
Anthropic (Claude API)Theme analysis, drafting your search configuration, and naming Your Vibe groupsTheme source excerpts; catalog samples (product titles, descriptions, category, product type, vendor, collections, options, selected metafields, and product image URLs); titles, vendors, and types of a shopper’s saved products. No order data and no shopper identifiers
ResendSends operational email to merchantsMerchant email address and message content
Logtail (Better Stack)Optional log aggregation, used only when configuredApplication logs

We will update the sub-processor list before adding or replacing a provider that processes merchant or shopper data.

VIBE’s own service data (configuration, search events, aggregated analytics, billing records, sessions) is stored in:

  • PostgreSQL: primary application database
  • Typesense: the search index, one collection per store
  • Redis: background job queue and cache

These run on VIBE’s hosted infrastructure. The providers listed in section 6 may store or process data in the regions described by their own terms, data processing agreements, and sub-processor notices.

Your Shopify access tokens, session refresh tokens, Storefront API access token and storefront password are encrypted at rest using AES-256-GCM before being stored. Session credentials are decrypted only when needed by the app or worker. Customer privacy request context and results are encrypted the same way. Encryption keys are derived from server-side secrets that are not stored in the database. Data in transit is protected with HTTPS/TLS between the app, Shopify, and sub-processors.

VIBE enforces its retention schedule automatically. A cleanup job runs weekly (Sunday, 03:00 UTC) and deletes data that has passed its retention period. A separate hourly sweep removes unmatched order lifecycle records older than 48 hours. A cleanup every 15 minutes removes expired order-job payloads and retries failed shop deletions. Age thresholds are applied on the next scheduled run; outages can delay a run. The main periods are:

Data typeRetention period
Search events and product impressions90 days
Order analytics lifecycle records48 hours when unmatched; 90 days when matched
Operational shop events (not billing or error)90 days
Operational shop events (billing or error)1 year
Merchant email delivery records90 days
Redacted order markers90 days
Daily analytics reports3 years
Monthly billing records3 years
Customer privacy request results7 days after the result is ready; see section 10
Shopify admin sessionsRemoved once expired

The full schedule, including cache and queue entries, is on the Data retention page.

On uninstall, VIBE schedules deletion for 30 days later as a fallback. Shopify normally sends a shop redaction request 48 hours after uninstall, which starts deletion sooner. Reinstalling can preserve configuration only if it has not already been deleted; there is no guaranteed 30-day recovery period (see section 10).

10. Your rights (merchants and shoppers) and how we handle them

Section titled “10. Your rights (merchants and shoppers) and how we handle them”

VIBE supports data-subject rights, including the right to access and the right to erasure, through Shopify’s mandatory compliance webhooks and the app’s Customer privacy page.

Customer data request (customers/data_request)

Section titled “Customer data request (customers/data_request)”
  1. Shopify sends the request to VIBE. VIBE records it durably, keeping only the request id, customer id, and order ids, encrypted. Nothing is returned inside the webhook response.
  2. A background job builds the result: every field VIBE keeps on the search events linked to the requested orders, including the events in the same visit and click chain, the product impressions attached to those events, and the minimal refund or cancellation lifecycle records for those orders. If no linked data exists, the result says so explicitly.
  3. The result is encrypted at rest. VIBE emails the verified store owner that it is ready. If no verified owner is on file yet, the notification waits until the store owner opens the app.
  4. The verified store owner downloads the result from Customer privacy in the app and shares it with the customer. Staff accounts cannot download it.
  5. The download expires 7 days after the result is ready. It can be prepared again from the same page while the request context is retained.

If the app has been uninstalled, contact support@coi.se. Support verifies the current store owner and arranges secure delivery.

VIBE deletes the search events, product impressions, and refund or cancellation lifecycle records linked to the order ids Shopify supplies, including the events in the same visit and click chain, removes those order ids from any pending request context, and invalidates prepared downloads. Before deletion, VIBE advances a per-store analytics high-water barrier 65 seconds beyond the request time. Direct and queued search-event inserts at or before that barrier are rejected, so pre-redaction analytics cannot be replayed after deletion, including events carrying the accepted one minute of future client-clock skew. VIBE keeps a marker of the redacted order ids for 90 days so a late paid-order notification cannot link them again.

VIBE deletes the store’s sessions and privacy request records immediately and starts a priority deletion job. The job waits for active shop work to finish, removes the installation’s queued and retained jobs and shop-specific Redis caches, and deletes the search index and database records, including related search events, analytics, rules, controls, email records and billing records. Temporary failures are retried. Shopify requires completion within 30 days of the request. The trial-eligibility record and internal staff audit records follow their separately stated retention periods.

On uninstall VIBE deletes the store’s sessions at once and schedules a fallback deletion for 30 days later. Shopify’s shop redaction webhook can start deletion earlier, normally after 48 hours. Reinstalling cancels the pending uninstall timer only while the configuration still exists. It cannot restore deleted data or cancel a mandatory redaction request.

Right to erasure for merchants is satisfied by the shop redaction and uninstall processes above.

VIBE does not currently provide a self-service merchant data export. You can request available account data, including billing records, rules, controls, and aggregated analytics, by contacting support@coi.se.

VIBE stores its identifiers in the browser’s own storage rather than in cookies it sets itself:

  • sessionStorage: the visit identifier and its last-activity time, the last clicked product (only with sales-tracking consent), short-lived Your Vibe caches, and a delivery-recovery queue for up to 20 analytics requests. Each queued request keeps its exact URL (which can contain the event type, query, visit id, product id, original occurrence time, replay nonce, and, when sales-tracking consent applies, vibe_aid) for at most 10 minutes so an interrupted navigation can retry it without double-counting. Successful requests are removed immediately, relevant consent withdrawal clears queued requests, and the queue is cleared when the tab closes. The server acknowledges but does not store a retryable request whose required occurrence time is missing, malformed, more than 15 minutes old, or more than one minute ahead of the server, preventing an old request from being recorded again as current activity.
  • localStorage: the attribution identifier vibe_aid (only with analytics and marketing consent), the shopper’s saved Your Vibe products, and a non-identifying one-bit pending-clear flag, per store. If Shopify cannot immediately remove __vibe_aid after consent withdrawal, the flag survives a tab or browser restart so a later page can retry; it is removed only after Shopify accepts the clear request.

The cart attribute __vibe_aid is set through Shopify’s cart, only with consent, and removed when consent is withdrawn. If you enable Google Tag Manager events, further storage is governed by your GTM configuration. VIBE does not use cross-site tracking.

VIBE is a business tool for Shopify merchants and is not directed at children. VIBE does not knowingly collect data from children.

We may update this policy from time to time. Material changes are reflected by updating the “Last updated” date and version at the top of this page. Continued use of the app after an update constitutes acknowledgment of the revised policy.

For privacy questions or requests relating to this policy, contact support@coi.se.

VIBE has not appointed a separate Data Protection Officer. Privacy requests sent to the support address above are routed to the responsible operator.