Projects
Organize links into projects for better management and campaign tracking.
Overview
Projects are folders that help you organize links within your organization. They're perfect for:
- Grouping links by campaign
- Separating client work
- Organizing by department or team
- Tracking project-specific analytics
Key Benefits:
- 📁 Organization - Group related links together
- 📊 Analytics - View aggregated metrics per project
- 🔍 Filtering - Quickly find links by project
- 👥 Collaboration - Share project context with team
Creating Projects
Via Dashboard
- Go to Projects in the sidebar
- Click "New Project"
- Enter project name
- (Optional) Add description
- Click "Create"
Via API
curl -X POST https://api.linkforty.com/api/projects \
-H "Authorization: Bearer $LINKFORTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring Sale 2024",
"description": "Instagram and email marketing campaign for Q1 spring sale"
}'
Response:
{
"id": "proj_abc123",
"user_id": "user_456",
"organization_id": "org_789",
"name": "Spring Sale 2024",
"description": "Instagram and email marketing campaign for Q1 spring sale",
"created_at": "2024-03-15T10:30:00Z",
"updated_at": "2024-03-15T10:30:00Z"
}
Requires: Member, Admin, or Owner role
Managing Projects
Viewing All Projects
Dashboard:
- Click "Projects" in sidebar
- See all projects with link counts
API:
curl https://api.linkforty.com/api/projects \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Response:
[
{
"id": "proj_123",
"name": "Spring Sale 2024",
"description": "Q1 spring sale campaign",
"created_at": "2024-03-15T10:30:00Z",
"updated_at": "2024-03-15T10:30:00Z"
},
{
"id": "proj_456",
"name": "Product Launch",
"description": "New product launch links",
"created_at": "2024-02-01T14:00:00Z",
"updated_at": "2024-02-10T09:15:00Z"
}
]
Getting Project Details
API:
curl https://api.linkforty.com/api/projects/proj_abc123 \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Response:
{
"id": "proj_abc123",
"user_id": "user_456",
"organization_id": "org_789",
"name": "Spring Sale 2024",
"description": "Instagram and email marketing campaign for Q1 spring sale",
"created_at": "2024-03-15T10:30:00Z",
"updated_at": "2024-03-15T10:30:00Z"
}
Updating Projects
Dashboard:
- Go to Projects
- Click project name
- Click "Edit"
- Update name or description
- Click "Save"
API:
curl -X PUT https://api.linkforty.com/api/projects/proj_abc123 \
-H "Authorization: Bearer $LINKFORTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring Sale 2024 - Extended",
"description": "Extended through April due to success"
}'
Requires: Member, Admin, or Owner role
Deleting Projects
⚠️ Warning: Deleting a project does NOT delete the links inside. Links are unassigned and remain in your organization.
Dashboard:
- Go to Projects
- Click project
- Click "Settings" → "Delete Project"
- Confirm deletion
API:
curl -X DELETE https://api.linkforty.com/api/projects/proj_abc123 \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Response:
{
"success": true
}
Requires: Admin or Owner role (for deletion)
Assigning Links to Projects
During Link Creation
Dashboard:
- Click "Create Link"
- Select project from dropdown
- Fill in link details
- Click "Create"
API:
curl -X POST https://api.linkforty.com/api/links \
-H "Authorization: Bearer $LINKFORTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"originalUrl": "https://shop.example.com/spring-sale",
"projectId": "proj_abc123",
"title": "Instagram Story - Spring Sale"
}'
For Existing Links
Dashboard:
- Go to Links
- Click link to edit
- Select project from dropdown
- Click "Save"
API:
curl -X PUT https://api.linkforty.com/api/links/link_xyz789 \
-H "Authorization: Bearer $LINKFORTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"projectId": "proj_abc123"
}'
Filtering Links by Project
Dashboard:
- Go to Links
- Use project filter dropdown
- Select project
API:
curl "https://api.linkforty.com/api/links?projectId=proj_abc123" \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Project Analytics
View aggregated analytics for all links in a project.
Via Dashboard
- Go to Projects
- Click project name
- View analytics tab
Via API
curl "https://api.linkforty.com/api/analytics/projects/proj_abc123?days=30" \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Response:
{
"totalClicks": 5432,
"uniqueClicks": 3821,
"clicksByDate": [
{
"date": "2024-03-15",
"clicks": 245
},
{
"date": "2024-03-14",
"clicks": 198
}
],
"clicksByCountry": [
{
"country": "US",
"clicks": 2341
},
{
"country": "CA",
"clicks": 987
}
],
"clicksByDevice": [
{
"device": "mobile",
"clicks": 3876
},
{
"device": "desktop",
"clicks": 1234
},
{
"device": "tablet",
"clicks": 322
}
],
"clicksByPlatform": [
{
"platform": "iOS",
"clicks": 2145
},
{
"platform": "Android",
"clicks": 1731
},
{
"platform": "Windows",
"clicks": 1556
}
]
}
Query Parameters:
days- Number of days to include (default: 30, max: 365)
Common Workflows
1. Campaign Organization
Setup:
async function setupCampaignProjects() {
const campaigns = [
{ name: 'Q1 Email Campaign', description: 'Weekly newsletter links' },
{ name: 'Instagram Ads - March', description: 'Paid social media ads' },
{ name: 'Product Launch', description: 'New product announcement' },
];
for (const campaign of campaigns) {
await fetch('https://api.linkforty.com/api/projects', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(campaign),
});
}
}
2. Agency Client Organization
Pattern:
Organization: Marketing Agency
├── Project: Client - Nike
├── Project: Client - Adidas
├── Project: Client - Under Armour
└── Project: Internal - Agency Website
Code:
async function createClientProject(clientName: string) {
const response = await fetch('https://api.linkforty.com/api/projects', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `Client - ${clientName}`,
description: `All links and campaigns for ${clientName}`,
}),
});
return response.json();
}
3. Department Organization
Pattern:
Organization: Acme Corp
├── Project: Marketing Team
├── Project: Sales Team
├── Project: Product Team
└── Project: Customer Success
4. Time-Based Projects
Pattern:
Organization: E-commerce Store
├── Project: January 2024
├── Project: February 2024
├── Project: March 2024
└── Project: Q1 Summary
TypeScript Examples
1. Create Project and Add Links
interface Project {
id: string;
name: string;
description?: string;
created_at: string;
updated_at: string;
}
interface Link {
id: string;
shortCode: string;
originalUrl: string;
projectId?: string;
title?: string;
}
async function createProjectWithLinks(
projectName: string,
links: Array<{ url: string; title: string }>
): Promise<{ project: Project; links: Link[] }> {
// Create project
const projectResponse = await fetch('https://api.linkforty.com/api/projects', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: projectName }),
});
const project = await projectResponse.json();
// Create links assigned to project
const createdLinks = [];
for (const link of links) {
const linkResponse = await fetch('https://api.linkforty.com/api/links', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
originalUrl: link.url,
title: link.title,
projectId: project.id,
}),
});
createdLinks.push(await linkResponse.json());
}
return { project, links: createdLinks };
}
// Usage
const campaign = await createProjectWithLinks('Spring Sale', [
{ url: 'https://shop.com/sale', title: 'Instagram Story 1' },
{ url: 'https://shop.com/sale', title: 'Email Newsletter' },
{ url: 'https://shop.com/sale', title: 'Facebook Ad' },
]);
console.log(`Created project: ${campaign.project.name}`);
console.log(`Created ${campaign.links.length} links`);
2. Compare Project Performance
async function compareProjectPerformance(
projectIds: string[],
days: number = 30
) {
const results = await Promise.all(
projectIds.map(async id => {
const analyticsResponse = await fetch(
`https://api.linkforty.com/api/analytics/projects/${id}?days=${days}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const analytics = await analyticsResponse.json();
const projectResponse = await fetch(
`https://api.linkforty.com/api/projects/${id}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const project = await projectResponse.json();
return {
projectId: id,
projectName: project.name,
totalClicks: analytics.totalClicks,
uniqueClicks: analytics.uniqueClicks,
clickThroughRate: (
(analytics.uniqueClicks / analytics.totalClicks) * 100
).toFixed(1) + '%',
};
})
);
// Sort by total clicks
return results.sort((a, b) => b.totalClicks - a.totalClicks);
}
// Usage
const comparison = await compareProjectPerformance([
'proj_123',
'proj_456',
'proj_789',
]);
console.table(comparison);
3. Archive Old Projects
async function archiveOldProjects(monthsOld: number = 6) {
const response = await fetch('https://api.linkforty.com/api/projects', {
headers: { 'Authorization': `Bearer ${API_KEY}` },
});
const projects: Project[] = await response.json();
const cutoffDate = new Date();
cutoffDate.setMonth(cutoffDate.getMonth() - monthsOld);
const oldProjects = projects.filter(project => {
const createdAt = new Date(project.created_at);
return createdAt < cutoffDate;
});
for (const project of oldProjects) {
// Check if project has any links
const linksResponse = await fetch(
`https://api.linkforty.com/api/links?projectId=${project.id}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const links = await linksResponse.json();
if (links.length === 0) {
// Delete empty old projects
await fetch(`https://api.linkforty.com/api/projects/${project.id}`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${API_KEY}` },
});
console.log(`✅ Deleted empty project: ${project.name}`);
} else {
// Rename to mark as archived
await fetch(`https://api.linkforty.com/api/projects/${project.id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `[ARCHIVED] ${project.name}`,
}),
});
console.log(`📦 Archived project: ${project.name}`);
}
}
}
4. Generate Project Report
async function generateProjectReport(projectId: string) {
// Get project details
const projectResponse = await fetch(
`https://api.linkforty.com/api/projects/${projectId}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const project = await projectResponse.json();
// Get project analytics
const analyticsResponse = await fetch(
`https://api.linkforty.com/api/analytics/projects/${projectId}?days=30`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const analytics = await analyticsResponse.json();
// Get all links in project
const linksResponse = await fetch(
`https://api.linkforty.com/api/links?projectId=${projectId}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const links = await linksResponse.json();
return {
project: {
name: project.name,
description: project.description,
created: new Date(project.created_at).toLocaleDateString(),
},
summary: {
totalLinks: links.length,
totalClicks: analytics.totalClicks,
uniqueClicks: analytics.uniqueClicks,
avgClicksPerLink: (analytics.totalClicks / links.length).toFixed(1),
avgClicksPerDay: (analytics.totalClicks / 30).toFixed(1),
},
topCountries: analytics.clicksByCountry.slice(0, 5),
deviceBreakdown: analytics.clicksByDevice,
platformBreakdown: analytics.clicksByPlatform,
};
}
// Usage
const report = await generateProjectReport('proj_abc123');
console.log(JSON.stringify(report, null, 2));
5. Bulk Move Links to Project
async function moveLinksToProject(
linkIds: string[],
projectId: string
): Promise<{ success: number; failed: number }> {
let success = 0;
let failed = 0;
for (const linkId of linkIds) {
try {
await fetch(`https://api.linkforty.com/api/links/${linkId}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ projectId }),
});
success++;
} catch (error) {
console.error(`Failed to move link ${linkId}:`, error);
failed++;
}
}
return { success, failed };
}
// Usage
const result = await moveLinksToProject(
['link_1', 'link_2', 'link_3'],
'proj_abc123'
);
console.log(`✅ Moved ${result.success} links`);
console.log(`❌ Failed ${result.failed} links`);
Best Practices
1. Clear Naming Conventions
✅ Good:
- "Q1 2024 - Email Marketing"
- "Client: Nike - Spring Campaign"
- "Product Launch - New Widget"
- "Instagram Ads - March 2024"
❌ Bad:
- "Project 1"
- "Test"
- "Links"
- "Stuff"
2. Use Descriptions
const project = {
name: 'Spring Sale 2024',
description: 'Instagram stories and email newsletter links for Q1 spring sale promotion. Target: 10K clicks.'
};
3. Regular Cleanup
// Monthly cleanup
async function monthlyProjectCleanup() {
// Archive old projects
await archiveOldProjects(6);
// Delete empty archived projects older than 1 year
await archiveOldProjects(12);
}
4. Consistent Organization Scheme
Pick one pattern and stick to it:
Option A - By Time:
- Q1 2024
- Q2 2024
- Q3 2024
Option B - By Campaign:
- Spring Sale
- Summer Launch
- Black Friday
Option C - By Client (Agencies):
- Client: Nike
- Client: Adidas
- Client: Puma
Option D - By Channel:
- Email Marketing
- Instagram Ads
- LinkedIn Posts
5. Don't Over-Organize
When NOT to use projects:
- You have less than 10 links
- All links are for one campaign
- You're a solo user with simple needs
When to use projects:
- Managing 50+ links
- Multiple campaigns or clients
- Team collaboration
- Need separate analytics per campaign
Troubleshooting
"Project not found"
Cause: Project ID doesn't exist or not in your organization
Fix:
- List all projects:
GET /api/projects - Verify project ID
- Check organization context
Can't Delete Project
Cause: Insufficient permissions
Fix:
- Check your role (Admin or Owner required for deletion)
- Ask admin to delete project
- Note: Members can create but not delete projects
Links Not Showing in Project
Cause: Links not assigned to project
Fix:
- Edit link
- Select project from dropdown
- Save changes
Project Analytics Empty
Possible causes:
- No links in project
- Links have no clicks yet
- Filtering by too short time period
Fix:
- Verify links are assigned:
GET /api/links?projectId=proj_123 - Check link analytics individually
- Increase
daysparameter
Related Guides
- Organizations - Organization management
- Creating Links - Link creation with projects
- Analytics Dashboard - Understanding analytics
Next Steps
- Create your first project
- Assign existing links to projects
- Set up a naming convention
- Review project analytics regularly
- Archive old projects quarterly