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

# Social Feed

> Social activity feed and interaction system

## Overview

The Social Feed API provides social networking features including following customers and stores, activity feeds, product interactions, and social discovery. The feed respects privacy settings - private accounts only show content to followers.

**Location:** `convex/customers/feed.ts`

## Privacy Controls

The feed system respects customer privacy settings:

* **Private accounts** (default): Content only visible to followers
* **Public accounts**: Content visible to all users
* Users can always see their own content regardless of privacy settings

## Follow Customer

<ParamField path="followerCustomerId" type="Id<'customers'>" required>
  Customer doing the following
</ParamField>

<ParamField path="targetCustomerId" type="Id<'customers'>" required>
  Customer to follow
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  await convex.mutation(api.customers.feed.followCustomer, {
    followerCustomerId: "c123456789",
    targetCustomerId: "c987654321"
  });
  ```
</CodeGroup>

## Follow Store

<ParamField path="followerCustomerId" type="Id<'customers'>" required>
  Customer following the store
</ParamField>

<ParamField path="storeId" type="Id<'stores'>" required>
  Store to follow
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  await convex.mutation(api.customers.feed.followStore, {
    followerCustomerId: "c123456789",
    storeId: "j123456789"
  });
  ```
</CodeGroup>

## Like Product

<ParamField path="productId" type="Id<'products'>" required>
  Product to like
</ParamField>

<ParamField path="customerId" type="Id<'customers'>" required>
  Customer ID
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  await convex.mutation(api.customers.feed.likeProduct, {
    productId: "p123456789",
    customerId: "c123456789"
  });
  ```
</CodeGroup>

## Get Feed

Retrieve personalized product-focused activity feed for a customer. The feed respects privacy settings and only shows content the user is authorized to see. Uses custom cursor-based pagination where the cursor is a timestamp string.

<ParamField path="customerId" type="Id<'customers'>">
  Customer ID (defaults to authenticated user if omitted)
</ParamField>

<ParamField path="paginationOpts" type="PaginationOptions" required>
  Pagination options with `numItems` (1-100) and `cursor` (timestamp string or null for first page)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const feed = await convex.query(api.customers.feed.getFeed, {
    paginationOpts: { numItems: 20, cursor: null }
  });

  // Load next page
  const nextPage = await convex.query(api.customers.feed.getFeed, {
    paginationOpts: { numItems: 20, cursor: feed.continueCursor }
  });
  ```
</CodeGroup>

### Feed Content Types

The feed includes these activity types (filtered by privacy):

1. **Price Updates**: From followed stores and on liked products
2. **Product Likes**: From followed customers (only if you also like the product)
3. **Product Shares**: From followed customers
4. **Direct Shares**: Shared directly to you (always visible regardless of privacy)
5. **New Products**: From followed stores

<ResponseExample>
  ```json Response theme={null}
  {
    "page": [
      {
        "activityId": "pa123456789",
        "activityType": "product_liked",
        "activityTime": 1640995800000,
        "product": {
          "_id": "p123456789",
          "name": "Organic Apples",
          "price": 12.99,
          "primaryImageUrl": "https://storage.convex.dev/apples.jpg",
          "isLikedByCustomer": true,
          "store": {
            "_id": "j123456789",
            "name": "Fresh Market",
            "logoUrl": "https://storage.convex.dev/logo.jpg"
          }
        },
        "actorCustomer": {
          "_id": "c987654321",
          "name": "Jane Smith",
          "avatarUrl": "https://storage.convex.dev/jane.jpg"
        },
        "priceData": null,
        "shareData": null
      },
      {
        "activityId": "pa987654321",
        "activityType": "price_update",
        "activityTime": 1640995600000,
        "product": {
          "_id": "p555666777",
          "name": "Wireless Headphones",
          "price": 79.99,
          "primaryImageUrl": "https://storage.convex.dev/headphones.jpg",
          "isLikedByCustomer": false,
          "store": {
            "_id": "j987654321",
            "name": "Tech Store",
            "logoUrl": "https://storage.convex.dev/tech-logo.jpg"
          }
        },
        "actorCustomer": null,
        "priceData": {
          "oldPrice": 99.99,
          "newPrice": 79.99,
          "discountPercent": 20
        },
        "shareData": null
      }
    ],
    "isDone": false,
    "continueCursor": "1640995600000"
  }
  ```
</ResponseExample>

## Get Feed Debug Info

Debug helper to inspect feed data sources for a customer. Returns counts of followed customers, stores, and recent activity.

<ParamField path="customerId" type="Id<'customers'>">
  Customer ID (defaults to authenticated user if omitted)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const debugInfo = await convex.query(api.customers.feed.getFeedDebugInfo, {
    customerId: "c123456789"
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "customerId": "c123456789",
    "followedCustomersCount": 15,
    "followedStoresCount": 8,
    "totalShares": 10,
    "totalPromotions": 10,
    "recentSharesCount": 10,
    "recentPromotionsCount": 10
  }
  ```
</ResponseExample>

## Create Test Product Activity

Helper mutation to create test product activity events for development and testing purposes.

<ParamField path="productId" type="Id<'products'>" required>
  Product ID for the activity event
</ParamField>

<ParamField path="activityType" type="'price_update' | 'product_liked' | 'product_shared' | 'new_product'" required>
  Type of activity to create
</ParamField>

<ParamField path="customerId" type="Id<'customers'>">
  Optional actor customer ID
</ParamField>

<ParamField path="oldPrice" type="number">
  Previous price (for price\_update events)
</ParamField>

<ParamField path="newPrice" type="number">
  New price (for price\_update events)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const activityId = await convex.mutation(api.customers.feed.createTestProductActivity, {
    productId: "p123456789",
    activityType: "price_update",
    oldPrice: 99.99,
    newPrice: 79.99
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  "pa123456789"
  ```
</ResponseExample>

## Test Feed

Test function to validate feed functionality. Runs a feed query and returns diagnostic information.

<ParamField path="numItems" type="number">
  Number of items to request (default: 10)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const testResult = await convex.query(api.customers.feed.testFeed, {
    numItems: 5
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "message": "Product feed query successful",
    "feedLength": 5,
    "hasNextPage": true,
    "activityTypes": ["price_update", "product_liked", "product_shared"]
  }
  ```
</ResponseExample>

<Note>
  Social feed includes activity from followed customers and stores with real-time updates. Privacy-restricted content is automatically filtered out.
</Note>
