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

# Member Content

> Database-driven content access control

Member Content allows you to define access rules in your Gately dashboard and enforce them across your website.

## Overview

Instead of hardcoding access rules in HTML, you can:

1. Define content items in your dashboard
2. Set access rules (plans, custom conditions)
3. Reference content by ID in your code
4. SDK automatically enforces access

## Creating Member Content

### Via Dashboard

1. Go to **Gated Content** in your dashboard
2. Click **Create Content**
3. Configure:
   * Name (e.g., "Premium Course")
   * URL pattern (e.g., `/courses/*`)
   * Required plan(s)
   * Redirect URL for unauthorized users
4. Save

### Via API

```bash theme={null}
curl -X POST "https://api.usegately.com/api/v1/member-content" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Project-ID: your-project-id" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Premium Course",
    "url_pattern": "/courses/*",
    "required_plans": ["pro", "enterprise"],
    "redirect_url": "/upgrade"
  }'
```

## Checking Access

### SDK Method

```javascript theme={null}
const access = await gately.checkMemberContentAccess(contentId)

if (access.allowed) {
  // Show content
} else {
  // Handle denial
  console.log('Reason:', access.reason)
  console.log('Redirect to:', access.redirect_url)
}
```

### Response

```typescript theme={null}
interface MemberContentAccessResponse {
  allowed: boolean
  reason?: 'not_authenticated' | 'plan_required' | 'custom_rule'
  redirect_url?: string
  content?: MemberContent
}
```

## URL Pattern Matching

Define URL patterns to automatically protect pages:

| Pattern           | Matches                            |
| ----------------- | ---------------------------------- |
| `/dashboard`      | Exact match                        |
| `/courses/*`      | All pages under /courses/          |
| `/blog/premium-*` | Pages starting with /blog/premium- |
| `*`               | All pages                          |

## Auto Protection

Enable automatic protection based on URL patterns:

```javascript theme={null}
gately.initPageProtection({
  checkOnLoad: true,
  redirectIfDenied: true
})
```

When a page loads:

1. SDK checks URL against member content patterns
2. If match found, access is verified
3. Unauthorized users are redirected

## React Integration

```jsx theme={null}
import { useMemberContent } from '@gately/sdk'

function PremiumContent({ contentId }) {
  const { hasAccess, isLoading, reason } = useMemberContent(contentId)

  if (isLoading) {
    return <Spinner />
  }

  if (!hasAccess) {
    return (
      <div className="upgrade-prompt">
        <h2>Premium Content</h2>
        <p>Upgrade to access this content.</p>
        <Link to="/upgrade">Upgrade Now</Link>
      </div>
    )
  }

  return (
    <div>
      {/* Your premium content */}
    </div>
  )
}
```

## Plan-Based Access

### Single Plan

```javascript theme={null}
// Content requires "pro" plan
{
  "required_plans": ["pro"]
}
```

### Multiple Plans (OR)

```javascript theme={null}
// Content accessible to "pro" OR "enterprise"
{
  "required_plans": ["pro", "enterprise"]
}
```

### Plan Hierarchy

Configure plan hierarchy in settings:

```
free < starter < pro < enterprise
```

Users with higher plans automatically get access to lower-tier content.

## Custom Access Rules

For advanced scenarios, use custom rules:

```javascript theme={null}
// Via API
{
  "custom_rules": {
    "metadata.company_size": { "gte": 100 },
    "metadata.verified": true
  }
}
```

## Handling Denied Access

### Redirect

```javascript theme={null}
gately.initPageProtection({
  onAccessDenied: (content, reason) => {
    if (reason === 'not_authenticated') {
      window.location.href = '/login?redirect=' + encodeURIComponent(window.location.pathname)
    } else if (reason === 'plan_required') {
      window.location.href = '/upgrade'
    }
  }
})
```

### Show Upgrade Prompt

```javascript theme={null}
gately.initPageProtection({
  redirectIfDenied: false,
  onAccessDenied: (content, reason) => {
    showUpgradeModal({
      requiredPlan: content.required_plans[0],
      currentPlan: gately.getUser()?.plan_id
    })
  }
})
```

## Webhooks

Track content access attempts:

```json theme={null}
{
  "event": "content.access_denied",
  "data": {
    "content_id": "content_123",
    "user_id": "user_456",
    "reason": "plan_required",
    "url": "/courses/advanced"
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use Descriptive Names">
    Name content clearly (e.g., "Premium Video Course" not "Content 1").
  </Accordion>

  <Accordion title="Group Related Content">
    Use URL patterns to protect entire sections at once.
  </Accordion>

  <Accordion title="Provide Clear Upgrade Paths">
    Always show users how to get access to protected content.
  </Accordion>

  <Accordion title="Cache Access Checks">
    The SDK caches access checks to minimize API calls.
  </Accordion>
</AccordionGroup>
