Add SEO data generation and testing for bilingual pages

- Implemented SEO data structures for programmatic tool and collection pages.
- Created functions to build FAQs and content sections for SEO pages.
- Added tests to ensure at least 50 bilingual SEO pages are generated, no duplicate English slugs, and matching Arabic localized paths.
- Verified that both tool and collection SEO inventories are populated adequately.
This commit is contained in:
Your Name
2026-03-21 10:55:43 +02:00
parent a8a7ec55a2
commit c800f707e3
12 changed files with 1920 additions and 22 deletions

View File

@@ -159,6 +159,7 @@ def create_app(config_name=None):
from app.routes.pdf_extra import pdf_extra_bp
from app.routes.image_extra import image_extra_bp
from app.routes.barcode import barcode_bp
from app.routes.sitemap import sitemap_bp
app.register_blueprint(health_bp, url_prefix="/api")
app.register_blueprint(auth_bp, url_prefix="/api/auth")
@@ -192,5 +193,6 @@ def create_app(config_name=None):
app.register_blueprint(pdf_extra_bp, url_prefix="/api/pdf-tools")
app.register_blueprint(image_extra_bp, url_prefix="/api/image")
app.register_blueprint(barcode_bp, url_prefix="/api/barcode")
app.register_blueprint(sitemap_bp)
return app

View File

@@ -0,0 +1,166 @@
"""XML sitemap endpoint for runtime and direct backend access."""
from flask import Blueprint, Response, current_app
from app.extensions import limiter
sitemap_bp = Blueprint("sitemap", __name__)
STATIC_PAGES = [
("/", "daily", "1.0"),
("/about", "monthly", "0.4"),
("/contact", "monthly", "0.4"),
("/privacy", "yearly", "0.3"),
("/terms", "yearly", "0.3"),
("/pricing", "monthly", "0.7"),
("/blog", "weekly", "0.6"),
("/developers", "monthly", "0.5"),
]
BLOG_SLUGS = [
"how-to-compress-pdf-online",
"convert-images-without-losing-quality",
"ocr-extract-text-from-images",
"merge-split-pdf-files",
"ai-chat-with-pdf-documents",
]
TOOL_SLUGS = [
"pdf-to-word",
"word-to-pdf",
"compress-pdf",
"merge-pdf",
"split-pdf",
"rotate-pdf",
"pdf-to-images",
"images-to-pdf",
"watermark-pdf",
"remove-watermark-pdf",
"protect-pdf",
"unlock-pdf",
"page-numbers",
"reorder-pdf",
"extract-pages",
"pdf-editor",
"pdf-flowchart",
"pdf-to-excel",
"sign-pdf",
"crop-pdf",
"flatten-pdf",
"repair-pdf",
"pdf-metadata",
"image-converter",
"image-resize",
"compress-image",
"remove-background",
"image-crop",
"image-rotate-flip",
"ocr",
"chat-pdf",
"summarize-pdf",
"translate-pdf",
"extract-tables",
"html-to-pdf",
"qr-code",
"video-to-gif",
"word-counter",
"text-cleaner",
"pdf-to-pptx",
"excel-to-pdf",
"pptx-to-pdf",
"barcode-generator",
]
SEO_TOOL_SLUGS = [
"pdf-to-word",
"word-to-pdf",
"compress-pdf-online",
"convert-jpg-to-pdf",
"merge-pdf-files",
"remove-pdf-password",
"pdf-to-word-editable",
"convert-pdf-to-text",
"split-pdf-online",
"jpg-to-pdf",
"png-to-pdf",
"images-to-pdf-online",
"pdf-to-jpg",
"pdf-to-png",
"compress-pdf-for-email",
"compress-scanned-pdf",
"merge-pdf-online-free",
"combine-pdf-files",
"extract-pages-from-pdf",
"reorder-pdf-pages",
"rotate-pdf-pages",
"add-page-numbers-to-pdf",
"protect-pdf-with-password",
"unlock-pdf-online",
"watermark-pdf-online",
"remove-watermark-from-pdf",
"edit-pdf-online-free",
"pdf-to-excel-online",
"extract-tables-from-pdf",
"html-to-pdf-online",
"scan-pdf-to-text",
"chat-with-pdf",
"summarize-pdf-online",
"translate-pdf-online",
"convert-image-to-pdf",
"convert-webp-to-jpg",
"resize-image-online",
"compress-image-online",
"remove-image-background",
]
SEO_COLLECTION_SLUGS = [
"best-pdf-tools",
"free-pdf-tools-online",
"convert-files-online",
"pdf-converter-tools",
"secure-pdf-tools",
"ai-document-tools",
"image-to-pdf-tools",
"online-image-tools",
"office-to-pdf-tools",
"scanned-document-tools",
"arabic-pdf-tools",
]
def _site_origin() -> str:
return str(current_app.config.get("SITE_DOMAIN", "https://dociva.io")).strip().rstrip("/")
def _url_tag(loc: str, changefreq: str, priority: str) -> str:
return (
" <url>\n"
f" <loc>{loc}</loc>\n"
" <lastmod>2026-03-21</lastmod>\n"
f" <changefreq>{changefreq}</changefreq>\n"
f" <priority>{priority}</priority>\n"
" </url>"
)
@sitemap_bp.route("/sitemap.xml", methods=["GET"])
@limiter.exempt
def sitemap_xml() -> Response:
"""Return an XML sitemap for direct backend access."""
origin = _site_origin()
entries = []
entries.extend(_url_tag(f"{origin}{path}", changefreq, priority) for path, changefreq, priority in STATIC_PAGES)
entries.extend(_url_tag(f"{origin}/blog/{slug}", "monthly", "0.6") for slug in BLOG_SLUGS)
entries.extend(_url_tag(f"{origin}/tools/{slug}", "weekly", "0.8") for slug in TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/{slug}", "weekly", "0.88") for slug in SEO_TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/ar/{slug}", "weekly", "0.8") for slug in SEO_TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/{slug}", "weekly", "0.82") for slug in SEO_COLLECTION_SLUGS)
entries.extend(_url_tag(f"{origin}/ar/{slug}", "weekly", "0.74") for slug in SEO_COLLECTION_SLUGS)
xml = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
+ "\n".join(entries)
+ "\n</urlset>\n"
)
return Response(xml, mimetype="application/xml")

View File

@@ -0,0 +1,13 @@
"""Tests for XML sitemap exposure."""
def test_sitemap_endpoint(client):
response = client.get('/sitemap.xml')
assert response.status_code == 200
assert 'xml' in response.content_type
body = response.get_data(as_text=True)
assert 'https://dociva.io/tools/pdf-to-word' in body
assert 'https://dociva.io/pdf-to-word' in body
assert 'https://dociva.io/ar/pdf-to-word' in body
assert 'https://dociva.io/arabic-pdf-tools' in body

View File

@@ -372,6 +372,438 @@
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/pdf-to-word-editable</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/convert-pdf-to-text</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/split-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/jpg-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/png-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/images-to-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/pdf-to-jpg</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/pdf-to-png</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/compress-pdf-for-email</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/compress-scanned-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/merge-pdf-online-free</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/combine-pdf-files</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/extract-pages-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/reorder-pdf-pages</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/rotate-pdf-pages</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/add-page-numbers-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/protect-pdf-with-password</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/unlock-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/watermark-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/remove-watermark-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/edit-pdf-online-free</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/pdf-to-excel-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/extract-tables-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/html-to-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/scan-pdf-to-text</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/chat-with-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/summarize-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/translate-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/convert-image-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/convert-webp-to-jpg</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/resize-image-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/compress-image-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/remove-image-background</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.88</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-to-word</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/word-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/compress-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/convert-jpg-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/merge-pdf-files</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/remove-pdf-password</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-to-word-editable</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/convert-pdf-to-text</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/split-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/jpg-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/png-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/images-to-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-to-jpg</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-to-png</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/compress-pdf-for-email</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/compress-scanned-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/merge-pdf-online-free</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/combine-pdf-files</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/extract-pages-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/reorder-pdf-pages</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/rotate-pdf-pages</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/add-page-numbers-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/protect-pdf-with-password</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/unlock-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/watermark-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/remove-watermark-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/edit-pdf-online-free</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-to-excel-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/extract-tables-from-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/html-to-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/scan-pdf-to-text</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/chat-with-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/summarize-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/translate-pdf-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/convert-image-to-pdf</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/convert-webp-to-jpg</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/resize-image-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/compress-image-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/ar/remove-image-background</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://dociva.io/best-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
@@ -390,4 +822,118 @@
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/pdf-converter-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/secure-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/ai-document-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/image-to-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/online-image-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/office-to-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/scanned-document-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/arabic-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.82</priority>
</url>
<url>
<loc>https://dociva.io/ar/best-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/free-pdf-tools-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/convert-files-online</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/pdf-converter-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/secure-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/ai-document-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/image-to-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/online-image-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/office-to-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/scanned-document-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
<url>
<loc>https://dociva.io/ar/arabic-pdf-tools</loc>
<lastmod>2026-03-21</lastmod>
<changefreq>weekly</changefreq>
<priority>0.74</priority>
</url>
</urlset>

View File

@@ -10,7 +10,7 @@ const siteOrigin = String(process.env.VITE_SITE_DOMAIN || 'https://dociva.io').t
const today = new Date().toISOString().slice(0, 10);
const seoConfig = JSON.parse(
await readFile(path.join(frontendRoot, 'src', 'config', 'seo-tools.json'), 'utf8')
await readFile(path.join(frontendRoot, 'src', 'seo', 'seoData.json'), 'utf8')
);
const staticPages = [
@@ -91,12 +91,18 @@ const sitemapEntries = [
...[...toolRoutePriorities.entries()].map(([slug, priority]) =>
makeUrlTag({ loc: `${siteOrigin}/tools/${slug}`, changefreq: 'weekly', priority })
),
...seoConfig.toolPages.map((page) =>
...seoConfig.toolPageSeeds.map((page) =>
makeUrlTag({ loc: `${siteOrigin}/${page.slug}`, changefreq: 'weekly', priority: '0.88' })
),
...seoConfig.collectionPages.map((page) =>
...seoConfig.toolPageSeeds.map((page) =>
makeUrlTag({ loc: `${siteOrigin}/ar/${page.slug}`, changefreq: 'weekly', priority: '0.8' })
),
...seoConfig.collectionPageSeeds.map((page) =>
makeUrlTag({ loc: `${siteOrigin}/${page.slug}`, changefreq: 'weekly', priority: '0.82' })
),
...seoConfig.collectionPageSeeds.map((page) =>
makeUrlTag({ loc: `${siteOrigin}/ar/${page.slug}`, changefreq: 'weekly', priority: '0.74' })
),
];
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${sitemapEntries.join('\n')}\n</urlset>\n`;

View File

@@ -17,6 +17,8 @@ interface SEOHeadProps {
type?: string;
/** Optional JSON-LD objects to inject as structured data */
jsonLd?: object | object[];
/** Optional explicit language alternates when route-based locale paths are required */
alternates?: Array<{ hrefLang: string; href: string; ogLocale?: string }>;
}
/**
@@ -27,13 +29,13 @@ interface SEOHeadProps {
* - Twitter card meta tags
* - Optional JSON-LD structured data
*/
export default function SEOHead({ title, description, keywords, path, type = 'website', jsonLd }: SEOHeadProps) {
export default function SEOHead({ title, description, keywords, path, type = 'website', jsonLd, alternates }: SEOHeadProps) {
const { i18n } = useTranslation();
const origin = getSiteOrigin(typeof window !== 'undefined' ? window.location.origin : '');
const canonicalUrl = `${origin}${path}`;
const socialImageUrl = buildSocialImageUrl(origin);
const fullTitle = `${title}${SITE_NAME}`;
const languageAlternates = buildLanguageAlternates(origin, path);
const languageAlternates = alternates ?? buildLanguageAlternates(origin, path);
const currentOgLocale = getOgLocale(i18n.language);
const schemas = jsonLd ? (Array.isArray(jsonLd) ? jsonLd : [jsonLd]) : [];

View File

@@ -1,4 +1,8 @@
import seoToolsConfig from '@/config/seo-tools.json';
import {
PROGRAMMATIC_TOOL_PAGES,
SEO_COLLECTION_PAGES,
getLocalizedSeoLandingPaths,
} from '@/seo/seoData';
export type SeoLocale = 'en' | 'ar';
@@ -17,6 +21,11 @@ export interface SeoFaqTemplate {
answer: LocalizedText;
}
export interface SeoContentSection {
heading: LocalizedText;
body: LocalizedText;
}
export interface ProgrammaticToolPage {
slug: string;
toolSlug: string;
@@ -27,6 +36,7 @@ export interface ProgrammaticToolPage {
descriptionTemplate: LocalizedText;
faqTemplates: SeoFaqTemplate[];
relatedCollectionSlugs: string[];
contentSections?: SeoContentSection[];
}
export interface SeoCollectionPage {
@@ -39,18 +49,9 @@ export interface SeoCollectionPage {
targetToolSlugs: string[];
faqTemplates: SeoFaqTemplate[];
relatedCollectionSlugs: string[];
contentSections?: SeoContentSection[];
}
interface SeoToolsConfig {
toolPages: ProgrammaticToolPage[];
collectionPages: SeoCollectionPage[];
}
const config = seoToolsConfig as SeoToolsConfig;
export const PROGRAMMATIC_TOOL_PAGES = config.toolPages;
export const SEO_COLLECTION_PAGES = config.collectionPages;
export function normalizeSeoLocale(language: string): SeoLocale {
return language.toLowerCase().startsWith('ar') ? 'ar' : 'en';
}
@@ -86,3 +87,7 @@ export function getAllCollectionSeoPaths(): string[] {
export function getAllSeoLandingPaths(): string[] {
return [...getAllProgrammaticSeoPaths(), ...getAllCollectionSeoPaths()];
}
export function getAllLocalizedSeoLandingPaths(): string[] {
return [...getLocalizedSeoLandingPaths('en'), ...getLocalizedSeoLandingPaths('ar')];
}

View File

@@ -64,9 +64,7 @@ export default function SeoCollectionPage({ slug }: SeoCollectionPageProps) {
const description = interpolateTemplate(getLocalizedText(page.descriptionTemplate, locale), tokens);
const intro = interpolateTemplate(getLocalizedText(page.introTemplate, locale), tokens);
const keywords = [focusKeyword, ...getLocalizedTextList(page.supportingKeywords, locale)].join(', ');
const path = `/${page.slug}`;
const siteOrigin = getSiteOrigin(typeof window !== 'undefined' ? window.location.origin : '');
const url = `${siteOrigin}${path}`;
const faqItems = page.faqTemplates.map((item) => ({
question: getLocalizedText(item.question, locale),
answer: getLocalizedText(item.answer, locale),
@@ -74,6 +72,13 @@ export default function SeoCollectionPage({ slug }: SeoCollectionPageProps) {
const relatedCollections = page.relatedCollectionSlugs
.map((collectionSlug) => getSeoCollectionPage(collectionSlug))
.filter((entry): entry is NonNullable<typeof entry> => Boolean(entry));
const contentSections = page.contentSections ?? [];
const path = locale === 'ar' ? `/ar/${page.slug}` : `/${page.slug}`;
const url = `${siteOrigin}${path}`;
const alternates = [
{ hrefLang: 'en', href: `${siteOrigin}/${page.slug}`, ogLocale: 'en_US' },
{ hrefLang: 'ar', href: `${siteOrigin}/ar/${page.slug}`, ogLocale: 'ar_SA' },
];
const jsonLd = [
generateWebPage({
@@ -91,7 +96,7 @@ export default function SeoCollectionPage({ slug }: SeoCollectionPageProps) {
return (
<>
<SEOHead title={title} description={description} path={path} keywords={keywords} jsonLd={jsonLd} />
<SEOHead title={title} description={description} path={path} keywords={keywords} jsonLd={jsonLd} alternates={alternates} />
<div className="mx-auto max-w-6xl space-y-10">
<section className="rounded-[2rem] border border-slate-200 bg-white p-8 shadow-sm dark:border-slate-700 dark:bg-slate-900/70 sm:p-10">
@@ -166,6 +171,21 @@ export default function SeoCollectionPage({ slug }: SeoCollectionPageProps) {
</ul>
</section>
{contentSections.length > 0 ? (
<section className="grid gap-6 lg:grid-cols-2">
{contentSections.map((section) => (
<article key={section.heading.en} className="rounded-2xl border border-slate-200 bg-white p-7 shadow-sm dark:border-slate-700 dark:bg-slate-900/70">
<h2 className="text-2xl font-semibold text-slate-900 dark:text-white">
{getLocalizedText(section.heading, locale)}
</h2>
<p className="mt-4 leading-8 text-slate-700 dark:text-slate-300">
{getLocalizedText(section.body, locale)}
</p>
</article>
))}
</section>
) : null}
<section className="rounded-2xl border border-slate-200 bg-white p-7 shadow-sm dark:border-slate-700 dark:bg-slate-900/70">
<h2 className="text-2xl font-semibold text-slate-900 dark:text-white">
{copy.relatedHeading}
@@ -180,12 +200,12 @@ export default function SeoCollectionPage({ slug }: SeoCollectionPageProps) {
return (
<Link
key={collection.slug}
to={`/${collection.slug}`}
to={locale === 'ar' ? `/ar/${collection.slug}` : `/${collection.slug}`}
className="rounded-2xl border border-slate-200 p-5 transition-colors hover:border-primary-300 hover:bg-slate-50 dark:border-slate-700 dark:hover:border-primary-600 dark:hover:bg-slate-800"
>
<div className="flex items-center gap-2 text-primary-600 dark:text-primary-400">
<Link2 className="h-4 w-4" />
<span className="text-sm font-medium">/{collection.slug}</span>
<span className="text-sm font-medium">{locale === 'ar' ? `/ar/${collection.slug}` : `/${collection.slug}`}</span>
</div>
<p className="mt-3 font-semibold text-slate-900 dark:text-white">{collectionTitle}</p>
</Link>

View File

@@ -98,6 +98,7 @@ export default function SeoPage({ slug }: SeoPageProps) {
const relatedCollections = page.relatedCollectionSlugs
.map((collectionSlug) => getSeoCollectionPage(collectionSlug))
.filter((entry): entry is NonNullable<typeof entry> => Boolean(entry));
const contentSections = page.contentSections ?? [];
const introBody = `${toolDescription} ${description}`;
const workflowBody = `${t(`seo.${tool.i18nKey}.whatItDoes`)} ${t(`tools.${tool.i18nKey}.shortDesc`)}`;
@@ -108,6 +109,10 @@ export default function SeoPage({ slug }: SeoPageProps) {
return relatedTool ? t(`tools.${relatedTool.i18nKey}.title`) : relatedSlug;
});
const localizedCollectionPath = (collectionSlug: string) => (locale === 'ar' ? `/ar/${collectionSlug}` : `/${collectionSlug}`);
const alternates = [
{ hrefLang: 'en', href: `${siteOrigin}/${page.slug}`, ogLocale: 'en_US' },
{ hrefLang: 'ar', href: `${siteOrigin}/ar/${page.slug}`, ogLocale: 'ar_SA' },
];
const jsonLd = [
generateWebPage({
@@ -137,7 +142,7 @@ export default function SeoPage({ slug }: SeoPageProps) {
return (
<>
<SEOHead title={title} description={description} path={path} keywords={keywords} jsonLd={jsonLd} />
<SEOHead title={title} description={description} path={path} keywords={keywords} jsonLd={jsonLd} alternates={alternates} />
<div className="mx-auto max-w-6xl space-y-12">
<section className="rounded-[2rem] border border-slate-200 bg-white p-8 shadow-sm dark:border-slate-700 dark:bg-slate-900/70 sm:p-10">
@@ -230,6 +235,21 @@ export default function SeoPage({ slug }: SeoPageProps) {
</div>
</section>
{contentSections.length > 0 ? (
<section className="grid gap-6 lg:grid-cols-2">
{contentSections.map((section) => (
<article key={section.heading.en} className="rounded-2xl border border-slate-200 bg-white p-7 shadow-sm dark:border-slate-700 dark:bg-slate-900/70">
<h2 className="text-2xl font-semibold text-slate-900 dark:text-white">
{getLocalizedText(section.heading, locale)}
</h2>
<p className="mt-4 leading-8 text-slate-700 dark:text-slate-300">
{getLocalizedText(section.body, locale)}
</p>
</article>
))}
</section>
) : null}
<section className="rounded-2xl border border-slate-200 bg-white p-7 shadow-sm dark:border-slate-700 dark:bg-slate-900/70">
<h2 className="text-2xl font-semibold text-slate-900 dark:text-white">
{copy.relatedHeading}

View File

@@ -0,0 +1,901 @@
{
"toolPageSeeds": [
{
"slug": "pdf-to-word",
"toolSlug": "pdf-to-word",
"category": "PDF",
"focusKeyword": { "en": "pdf to word", "ar": "تحويل PDF إلى Word" },
"supportingKeywords": {
"en": ["pdf to docx", "convert pdf to word online", "editable word from pdf"],
"ar": ["تحويل pdf الى word", "تحويل pdf إلى docx", "تحويل ملف pdf إلى وورد"]
},
"benefit": {
"en": "Turn fixed PDF pages into editable Word files without rebuilding the document from scratch.",
"ar": "حوّل صفحات PDF الثابتة إلى ملفات Word قابلة للتحرير بدون إعادة بناء المستند من البداية."
},
"useCase": {
"en": "Best for contracts, resumes, reports, and client revisions.",
"ar": "مناسب للعقود والسير الذاتية والتقارير وتعديلات العملاء."
},
"relatedCollectionSlugs": ["best-pdf-tools", "convert-files-online"]
},
{
"slug": "word-to-pdf",
"toolSlug": "word-to-pdf",
"category": "Convert",
"focusKeyword": { "en": "word to pdf", "ar": "تحويل Word إلى PDF" },
"supportingKeywords": {
"en": ["docx to pdf", "convert word to pdf online", "save word as pdf"],
"ar": ["تحويل وورد إلى pdf", "docx إلى pdf", "تحويل ملف word إلى pdf"]
},
"benefit": {
"en": "Create clean, shareable PDFs from Word files while preserving layout for print or approvals.",
"ar": "أنشئ ملفات PDF نظيفة وقابلة للمشاركة من ملفات Word مع الحفاظ على التنسيق للطباعة أو الاعتماد."
},
"useCase": {
"en": "Useful for proposals, handouts, policies, and invoices.",
"ar": "مفيد للعروض والمطبوعات والسياسات والفواتير."
},
"relatedCollectionSlugs": ["pdf-converter-tools", "office-to-pdf-tools"]
},
{
"slug": "compress-pdf-online",
"toolSlug": "compress-pdf",
"category": "PDF",
"focusKeyword": { "en": "compress pdf online", "ar": "ضغط PDF أونلاين" },
"supportingKeywords": {
"en": ["reduce pdf size", "make pdf smaller", "shrink pdf online"],
"ar": ["ضغط ملف pdf", "تقليل حجم pdf", "تصغير ملف pdf"]
},
"benefit": {
"en": "Reduce large PDFs so they are easier to email, upload, archive, and open on mobile devices.",
"ar": "قلّل حجم ملفات PDF الكبيرة لتصبح أسهل في الإرسال والرفع والأرشفة والفتح على الجوال."
},
"useCase": {
"en": "Ideal for email attachments, portals with size limits, and document archives.",
"ar": "مثالي لمرفقات البريد الإلكتروني والبوابات ذات حدود الحجم وأرشيف المستندات."
},
"relatedCollectionSlugs": ["free-pdf-tools-online", "best-pdf-tools"]
},
{
"slug": "convert-jpg-to-pdf",
"toolSlug": "images-to-pdf",
"category": "PDF",
"focusKeyword": { "en": "convert jpg to pdf", "ar": "تحويل JPG إلى PDF" },
"supportingKeywords": {
"en": ["jpg to pdf online", "photo to pdf", "combine jpg into pdf"],
"ar": ["تحويل jpg إلى pdf", "صورة إلى pdf", "دمج صور jpg في pdf"]
},
"benefit": {
"en": "Turn one or more JPG images into a single PDF document that is easier to share and print.",
"ar": "حوّل صورة JPG واحدة أو عدة صور إلى ملف PDF واحد أسهل في المشاركة والطباعة."
},
"useCase": {
"en": "Common for receipts, scanned pages, IDs, and application uploads.",
"ar": "شائع للإيصالات والصفحات الممسوحة ضوئياً وبطاقات الهوية وملفات التقديم."
},
"relatedCollectionSlugs": ["image-to-pdf-tools", "convert-files-online"]
},
{
"slug": "merge-pdf-files",
"toolSlug": "merge-pdf",
"category": "PDF",
"focusKeyword": { "en": "merge pdf files", "ar": "دمج ملفات PDF" },
"supportingKeywords": {
"en": ["combine pdf files", "join pdf online", "merge pdf documents"],
"ar": ["دمج ملفات pdf", "دمج pdf", "جمع ملفات pdf"]
},
"benefit": {
"en": "Combine multiple PDFs into one ordered file without changing the original page quality.",
"ar": "ادمج عدة ملفات PDF في ملف واحد مرتب بدون التأثير على جودة الصفحات الأصلية."
},
"useCase": {
"en": "Useful for proposals, legal packets, onboarding files, and reporting bundles.",
"ar": "مفيد للعروض والملفات القانونية وحزم onboarding وتجميع التقارير."
},
"relatedCollectionSlugs": ["best-pdf-tools", "secure-pdf-tools"]
},
{
"slug": "remove-pdf-password",
"toolSlug": "unlock-pdf",
"category": "PDF",
"focusKeyword": { "en": "remove pdf password", "ar": "إزالة كلمة مرور PDF" },
"supportingKeywords": {
"en": ["unlock pdf", "remove pdf protection", "open locked pdf"],
"ar": ["فتح قفل pdf", "إزالة حماية pdf", "إلغاء كلمة سر pdf"]
},
"benefit": {
"en": "Remove protection from PDFs you already have permission to open so editing and sharing are faster.",
"ar": "أزل الحماية من ملفات PDF التي لديك إذن بفتحها بالفعل حتى تصبح عملية التعديل والمشاركة أسرع."
},
"useCase": {
"en": "Helpful when teams need to print, review, merge, or archive secured files.",
"ar": "مفيد عندما تحتاج الفرق إلى طباعة الملفات المؤمنة أو مراجعتها أو دمجها أو أرشفتها."
},
"relatedCollectionSlugs": ["secure-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "pdf-to-word-editable",
"toolSlug": "pdf-to-word",
"category": "PDF",
"focusKeyword": { "en": "pdf to word editable", "ar": "تحويل PDF إلى Word قابل للتعديل" },
"supportingKeywords": {
"en": ["editable pdf to word", "make pdf editable in word", "pdf to editable docx"],
"ar": ["pdf إلى word قابل للتعديل", "تحويل pdf قابل للتحرير", "ملف وورد قابل للتعديل من pdf"]
},
"benefit": {
"en": "Create a Word version that can be revised quickly instead of retyping content from a static PDF.",
"ar": "أنشئ نسخة Word قابلة للتعديل بسرعة بدلاً من إعادة كتابة محتوى PDF ثابت يدوياً."
},
"useCase": {
"en": "Best for editable forms, vendor documents, and reused templates.",
"ar": "مناسب للنماذج القابلة للتعديل ووثائق الموردين والقوالب المعاد استخدامها."
},
"relatedCollectionSlugs": ["pdf-converter-tools", "scanned-document-tools"]
},
{
"slug": "convert-pdf-to-text",
"toolSlug": "ocr",
"category": "AI",
"focusKeyword": { "en": "convert pdf to text", "ar": "تحويل PDF إلى نص" },
"supportingKeywords": {
"en": ["pdf to text online", "extract text from pdf", "pdf text extraction"],
"ar": ["تحويل pdf إلى نص", "استخراج النص من pdf", "قراءة نص pdf"]
},
"benefit": {
"en": "Extract readable text from scanned or image-based PDFs so content becomes searchable and reusable.",
"ar": "استخرج نصاً قابلاً للقراءة من ملفات PDF الممسوحة ضوئياً أو المعتمدة على الصور ليصبح المحتوى قابلاً للبحث وإعادة الاستخدام."
},
"useCase": {
"en": "Useful for reports, scanned forms, research material, and document indexing.",
"ar": "مفيد للتقارير والنماذج الممسوحة ضوئياً ومواد البحث وفهرسة المستندات."
},
"relatedCollectionSlugs": ["ai-document-tools", "scanned-document-tools"]
},
{
"slug": "split-pdf-online",
"toolSlug": "split-pdf",
"category": "PDF",
"focusKeyword": { "en": "split pdf online", "ar": "تقسيم PDF أونلاين" },
"supportingKeywords": {
"en": ["split pdf pages", "divide pdf", "separate pdf pages"],
"ar": ["تقسيم ملف pdf", "فصل صفحات pdf", "تجزئة pdf"]
},
"benefit": {
"en": "Break large PDFs into smaller parts or isolate the exact pages you need for the next workflow.",
"ar": "قسّم ملفات PDF الكبيرة إلى أجزاء أصغر أو اعزل الصفحات التي تحتاجها فقط للمسار التالي."
},
"useCase": {
"en": "Helpful for chapter sharing, legal exhibits, and trimmed uploads.",
"ar": "مفيد لمشاركة الفصول والمرفقات القانونية ورفع ملفات مختصرة."
},
"relatedCollectionSlugs": ["best-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "jpg-to-pdf",
"toolSlug": "images-to-pdf",
"category": "PDF",
"focusKeyword": { "en": "jpg to pdf", "ar": "تحويل JPG إلى PDF" },
"supportingKeywords": {
"en": ["image to pdf", "jpg file to pdf", "convert jpg file to pdf"],
"ar": ["jpg إلى pdf", "تحويل صورة jpg إلى pdf", "تحويل الصور الى pdf"]
},
"benefit": {
"en": "Convert JPG files into a clean PDF format that works across devices and office workflows.",
"ar": "حوّل ملفات JPG إلى صيغة PDF نظيفة تعمل عبر الأجهزة ومسارات العمل المكتبية."
},
"useCase": {
"en": "Good for homework scans, receipts, forms, and proofs of identity.",
"ar": "جيد للواجبات الممسوحة ضوئياً والإيصالات والنماذج وإثباتات الهوية."
},
"relatedCollectionSlugs": ["image-to-pdf-tools", "arabic-pdf-tools"]
},
{
"slug": "png-to-pdf",
"toolSlug": "images-to-pdf",
"category": "PDF",
"focusKeyword": { "en": "png to pdf", "ar": "تحويل PNG إلى PDF" },
"supportingKeywords": {
"en": ["convert png to pdf", "png file to pdf", "png image pdf"],
"ar": ["تحويل png إلى pdf", "ملف png إلى pdf", "صورة png إلى pdf"]
},
"benefit": {
"en": "Package PNG images into PDF while keeping diagrams, screenshots, and transparency-heavy content organized.",
"ar": "حوّل صور PNG إلى PDF مع إبقاء المخططات ولقطات الشاشة والمحتوى المنظم بصورة مرتبة."
},
"useCase": {
"en": "Useful for mockups, screenshots, annotated notes, and design exports.",
"ar": "مفيد للنماذج الأولية ولقطات الشاشة والملاحظات المشروحة وتصدير التصاميم."
},
"relatedCollectionSlugs": ["image-to-pdf-tools", "online-image-tools"]
},
{
"slug": "images-to-pdf-online",
"toolSlug": "images-to-pdf",
"category": "PDF",
"focusKeyword": { "en": "images to pdf online", "ar": "تحويل الصور إلى PDF أونلاين" },
"supportingKeywords": {
"en": ["combine images into pdf", "multiple images to pdf", "photos to pdf online"],
"ar": ["تحويل الصور الى pdf", "دمج الصور في pdf", "عدة صور إلى pdf"]
},
"benefit": {
"en": "Combine multiple images into one portable PDF instead of sending several separate files.",
"ar": "ادمج عدة صور في ملف PDF واحد قابل للنقل بدلاً من إرسال عدة ملفات منفصلة."
},
"useCase": {
"en": "Useful for case files, property photos, receipts, and scanned homework.",
"ar": "مفيد لملفات القضايا وصور العقارات والإيصالات والواجبات الممسوحة ضوئياً."
},
"relatedCollectionSlugs": ["image-to-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "pdf-to-jpg",
"toolSlug": "pdf-to-images",
"category": "PDF",
"focusKeyword": { "en": "pdf to jpg", "ar": "تحويل PDF إلى JPG" },
"supportingKeywords": {
"en": ["convert pdf to jpg", "pdf page to image", "save pdf as jpg"],
"ar": ["تحويل pdf إلى jpg", "صفحات pdf إلى صور", "حفظ pdf كـ jpg"]
},
"benefit": {
"en": "Turn PDF pages into JPG images for quick previews, sharing in chat apps, or slide decks.",
"ar": "حوّل صفحات PDF إلى صور JPG للمعاينة السريعة أو المشاركة في تطبيقات المحادثة أو العروض."
},
"useCase": {
"en": "Best for presentations, social posts, proof snapshots, and lightweight sharing.",
"ar": "مناسب للعروض والمنشورات الاجتماعية ولقطات الإثبات والمشاركة الخفيفة."
},
"relatedCollectionSlugs": ["pdf-converter-tools", "convert-files-online"]
},
{
"slug": "pdf-to-png",
"toolSlug": "pdf-to-images",
"category": "PDF",
"focusKeyword": { "en": "pdf to png", "ar": "تحويل PDF إلى PNG" },
"supportingKeywords": {
"en": ["convert pdf to png", "pdf page to png", "high quality pdf image"],
"ar": ["تحويل pdf إلى png", "صفحة pdf إلى png", "صورة عالية الجودة من pdf"]
},
"benefit": {
"en": "Export crisp PNG images from PDF pages when clarity matters for screenshots, interfaces, or graphics.",
"ar": "صدّر صور PNG واضحة من صفحات PDF عندما تكون الدقة مهمة لواجهات الاستخدام أو الرسومات أو لقطات الشاشة."
},
"useCase": {
"en": "Good for annotated visuals, UI reviews, graphics handoff, and transparent workflows.",
"ar": "جيد للمرئيات المشروحة ومراجعات الواجهات وتسليم الرسومات ومسارات العمل التي تحتاج وضوحاً أعلى."
},
"relatedCollectionSlugs": ["pdf-converter-tools", "online-image-tools"]
},
{
"slug": "compress-pdf-for-email",
"toolSlug": "compress-pdf",
"category": "PDF",
"focusKeyword": { "en": "compress pdf for email", "ar": "ضغط PDF للإيميل" },
"supportingKeywords": {
"en": ["email pdf size limit", "reduce pdf for attachment", "small pdf for email"],
"ar": ["ضغط pdf للبريد", "تقليل حجم pdf للإرسال", "ملف pdf صغير للإيميل"]
},
"benefit": {
"en": "Shrink PDFs to meet common attachment limits without making documents unreadable.",
"ar": "قلّل حجم ملفات PDF لتوافق حدود المرفقات الشائعة بدون أن تصبح المستندات غير قابلة للقراءة."
},
"useCase": {
"en": "Useful for HR forms, vendor documents, client approvals, and support tickets.",
"ar": "مفيد لنماذج الموارد البشرية ووثائق الموردين وموافقات العملاء وتذاكر الدعم."
},
"relatedCollectionSlugs": ["free-pdf-tools-online", "secure-pdf-tools"]
},
{
"slug": "compress-scanned-pdf",
"toolSlug": "compress-pdf",
"category": "PDF",
"focusKeyword": { "en": "compress scanned pdf", "ar": "ضغط PDF ممسوح ضوئياً" },
"supportingKeywords": {
"en": ["reduce scanned pdf size", "scan pdf compressor", "shrink image-based pdf"],
"ar": ["ضغط ملف pdf ممسوح", "تقليل حجم pdf ممسوح", "ضغط pdf صور"]
},
"benefit": {
"en": "Cut the size of image-heavy scanned PDFs so they can be uploaded and shared more easily.",
"ar": "خفّض حجم ملفات PDF الممسوحة ضوئياً والغنية بالصور حتى يمكن رفعها ومشاركتها بسهولة أكبر."
},
"useCase": {
"en": "Helpful for archive scans, office paperwork, and portal submissions.",
"ar": "مفيد للأرشفة الممسوحة ضوئياً والأوراق المكتبية والرفع إلى البوابات."
},
"relatedCollectionSlugs": ["scanned-document-tools", "best-pdf-tools"]
},
{
"slug": "merge-pdf-online-free",
"toolSlug": "merge-pdf",
"category": "PDF",
"focusKeyword": { "en": "merge pdf online free", "ar": "دمج PDF أونلاين مجاناً" },
"supportingKeywords": {
"en": ["free merge pdf", "combine pdf online free", "join pdf files free"],
"ar": ["دمج pdf مجاناً", "جمع pdf أونلاين", "دمج ملفات pdf مجانا"]
},
"benefit": {
"en": "Assemble multiple PDFs into one document in the browser without extra desktop software.",
"ar": "اجمع عدة ملفات PDF في مستند واحد داخل المتصفح بدون برامج سطح مكتب إضافية."
},
"useCase": {
"en": "Common for bid packs, onboarding bundles, and document handoffs.",
"ar": "شائع لحزم العطاءات وملفات onboarding وتسليم المستندات."
},
"relatedCollectionSlugs": ["free-pdf-tools-online", "best-pdf-tools"]
},
{
"slug": "combine-pdf-files",
"toolSlug": "merge-pdf",
"category": "PDF",
"focusKeyword": { "en": "combine pdf files", "ar": "جمع ملفات PDF" },
"supportingKeywords": {
"en": ["combine multiple pdf files", "join pdf documents", "put pdf files together"],
"ar": ["جمع ملفات pdf", "تجميع مستندات pdf", "ضم ملفات pdf"]
},
"benefit": {
"en": "Put related PDF files together so teams review one document instead of many separate attachments.",
"ar": "اجمع ملفات PDF المرتبطة معاً حتى تراجع الفرق مستنداً واحداً بدلاً من عدة مرفقات منفصلة."
},
"useCase": {
"en": "Useful for applications, case files, board packs, and proposal sets.",
"ar": "مفيد لطلبات التقديم وملفات القضايا وحزم الاجتماعات ومجموعات العروض."
},
"relatedCollectionSlugs": ["best-pdf-tools", "office-to-pdf-tools"]
},
{
"slug": "extract-pages-from-pdf",
"toolSlug": "extract-pages",
"category": "PDF",
"focusKeyword": { "en": "extract pages from pdf", "ar": "استخراج صفحات من PDF" },
"supportingKeywords": {
"en": ["select pages from pdf", "save selected pdf pages", "pdf page extractor"],
"ar": ["استخراج صفحات من pdf", "حفظ صفحات pdf محددة", "أداة استخراج صفحات pdf"]
},
"benefit": {
"en": "Keep only the pages you need from a larger PDF before sending or reusing the document.",
"ar": "احتفظ فقط بالصفحات التي تحتاجها من ملف PDF أكبر قبل إرسال المستند أو إعادة استخدامه."
},
"useCase": {
"en": "Helpful for exhibits, chapter handoffs, and trimmed submissions.",
"ar": "مفيد للملاحق والفصول المقتطعة وعمليات الرفع المختصرة."
},
"relatedCollectionSlugs": ["best-pdf-tools", "secure-pdf-tools"]
},
{
"slug": "reorder-pdf-pages",
"toolSlug": "reorder-pdf",
"category": "PDF",
"focusKeyword": { "en": "reorder pdf pages", "ar": "إعادة ترتيب صفحات PDF" },
"supportingKeywords": {
"en": ["rearrange pdf pages", "organize pdf pages", "sort pages in pdf"],
"ar": ["إعادة ترتيب صفحات pdf", "تنظيم صفحات pdf", "تبديل صفحات pdf"]
},
"benefit": {
"en": "Fix page order in PDFs before sharing, printing, or merging with other files.",
"ar": "أصلح ترتيب الصفحات في ملفات PDF قبل المشاركة أو الطباعة أو الدمج مع ملفات أخرى."
},
"useCase": {
"en": "Useful for reports, scanned batches, contracts, and course packs.",
"ar": "مفيد للتقارير والدفعات الممسوحة ضوئياً والعقود وحزم الدروس."
},
"relatedCollectionSlugs": ["best-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "rotate-pdf-pages",
"toolSlug": "rotate-pdf",
"category": "PDF",
"focusKeyword": { "en": "rotate pdf pages", "ar": "تدوير صفحات PDF" },
"supportingKeywords": {
"en": ["rotate pdf online", "fix pdf orientation", "turn pdf pages"],
"ar": ["تدوير pdf", "تصحيح اتجاه pdf", "إدارة صفحات pdf"]
},
"benefit": {
"en": "Correct sideways or upside-down PDF pages so they read properly on screen and on paper.",
"ar": "صحّح صفحات PDF المائلة أو المقلوبة حتى تُقرأ بشكل صحيح على الشاشة وعلى الورق."
},
"useCase": {
"en": "Common for scans, phone-captured documents, and mixed page sets.",
"ar": "شائع للملفات الممسوحة ضوئياً والمستندات الملتقطة بالجوال ومجموعات الصفحات المختلطة."
},
"relatedCollectionSlugs": ["best-pdf-tools", "scanned-document-tools"]
},
{
"slug": "add-page-numbers-to-pdf",
"toolSlug": "page-numbers",
"category": "PDF",
"focusKeyword": { "en": "add page numbers to pdf", "ar": "إضافة أرقام الصفحات إلى PDF" },
"supportingKeywords": {
"en": ["pdf page numbering", "number pdf pages", "insert page numbers pdf"],
"ar": ["إضافة أرقام للصفحات في pdf", "ترقيم صفحات pdf", "أرقام صفحات pdf"]
},
"benefit": {
"en": "Add consistent numbering to PDFs so longer documents are easier to reference and review.",
"ar": "أضف ترقيمًا ثابتًا إلى ملفات PDF حتى يسهل الرجوع إلى المستندات الطويلة ومراجعتها."
},
"useCase": {
"en": "Useful for legal files, manuals, reports, and printed course packs.",
"ar": "مفيد للملفات القانونية والأدلة والتقارير وحزم الدراسة المطبوعة."
},
"relatedCollectionSlugs": ["best-pdf-tools", "office-to-pdf-tools"]
},
{
"slug": "protect-pdf-with-password",
"toolSlug": "protect-pdf",
"category": "PDF",
"focusKeyword": { "en": "protect pdf with password", "ar": "حماية PDF بكلمة مرور" },
"supportingKeywords": {
"en": ["password protect pdf", "secure pdf online", "encrypt pdf file"],
"ar": ["حماية pdf بكلمة مرور", "تأمين ملف pdf", "تشفير pdf"]
},
"benefit": {
"en": "Restrict access to PDFs before sending them outside your team or organization.",
"ar": "قيّد الوصول إلى ملفات PDF قبل إرسالها خارج فريقك أو مؤسستك."
},
"useCase": {
"en": "Useful for HR, finance, legal, and sensitive client documents.",
"ar": "مفيد لوثائق الموارد البشرية والمالية والقانونية ووثائق العملاء الحساسة."
},
"relatedCollectionSlugs": ["secure-pdf-tools", "best-pdf-tools"]
},
{
"slug": "unlock-pdf-online",
"toolSlug": "unlock-pdf",
"category": "PDF",
"focusKeyword": { "en": "unlock pdf online", "ar": "فتح قفل PDF أونلاين" },
"supportingKeywords": {
"en": ["unlock protected pdf", "remove password from pdf", "decrypt pdf online"],
"ar": ["فتح قفل pdf أونلاين", "إزالة كلمة المرور من pdf", "فك حماية pdf"]
},
"benefit": {
"en": "Open up protected PDFs that you are authorized to use so the next editing or sharing step is easier.",
"ar": "افتح ملفات PDF المحمية التي لديك تصريح باستخدامها حتى تصبح الخطوة التالية من التعديل أو المشاركة أسهل."
},
"useCase": {
"en": "Helpful before merging, printing, annotating, or converting files.",
"ar": "مفيد قبل الدمج أو الطباعة أو التعليق أو تحويل الملفات."
},
"relatedCollectionSlugs": ["secure-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "watermark-pdf-online",
"toolSlug": "watermark-pdf",
"category": "PDF",
"focusKeyword": { "en": "watermark pdf online", "ar": "وضع علامة مائية على PDF أونلاين" },
"supportingKeywords": {
"en": ["add watermark to pdf", "pdf watermark online", "brand pdf document"],
"ar": ["إضافة علامة مائية إلى pdf", "علامة مائية pdf", "وضع شعار على pdf"]
},
"benefit": {
"en": "Add a visible ownership layer to PDFs before sharing drafts, proofs, or client-facing documents.",
"ar": "أضف طبقة ملكية واضحة إلى ملفات PDF قبل مشاركة المسودات أو الإثباتات أو مستندات العملاء."
},
"useCase": {
"en": "Useful for draft reviews, branded exports, and controlled circulation.",
"ar": "مفيد لمراجعة المسودات والتصدير الممهور بالعلامة التجارية والتوزيع المحدود."
},
"relatedCollectionSlugs": ["secure-pdf-tools", "best-pdf-tools"]
},
{
"slug": "remove-watermark-from-pdf",
"toolSlug": "remove-watermark-pdf",
"category": "PDF",
"focusKeyword": { "en": "remove watermark from pdf", "ar": "إزالة العلامة المائية من PDF" },
"supportingKeywords": {
"en": ["delete pdf watermark", "clean pdf watermark", "remove text watermark pdf"],
"ar": ["إزالة العلامة المائية من pdf", "حذف العلامة المائية pdf", "تنظيف pdf من العلامة المائية"]
},
"benefit": {
"en": "Clean up PDFs by removing unwanted watermark text when you are working with authorized source files.",
"ar": "نظّف ملفات PDF بإزالة نص العلامة المائية غير المرغوب عندما تعمل على ملفات مصدر مصرح بها."
},
"useCase": {
"en": "Useful for final copies, internal working versions, and cleaned archives.",
"ar": "مفيد للنسخ النهائية ونسخ العمل الداخلية والأرشيفات النظيفة."
},
"relatedCollectionSlugs": ["secure-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "edit-pdf-online-free",
"toolSlug": "pdf-editor",
"category": "PDF",
"focusKeyword": { "en": "edit pdf online free", "ar": "تعديل PDF أونلاين مجاناً" },
"supportingKeywords": {
"en": ["free pdf editor online", "annotate pdf", "modify pdf online"],
"ar": ["تعديل pdf مجاناً", "محرر pdf أونلاين", "تعديل ملف pdf"]
},
"benefit": {
"en": "Make quick PDF edits and annotations in the browser without switching to heavier desktop software.",
"ar": "أجرِ تعديلات سريعة وتعليقات على PDF داخل المتصفح بدون الانتقال إلى برامج سطح مكتب أثقل."
},
"useCase": {
"en": "Useful for notes, approvals, markup, and light document cleanup.",
"ar": "مفيد للملاحظات والموافقات ووضع العلامات وتنظيف المستندات بشكل خفيف."
},
"relatedCollectionSlugs": ["free-pdf-tools-online", "best-pdf-tools"]
},
{
"slug": "pdf-to-excel-online",
"toolSlug": "pdf-to-excel",
"category": "Convert",
"focusKeyword": { "en": "pdf to excel online", "ar": "تحويل PDF إلى Excel أونلاين" },
"supportingKeywords": {
"en": ["convert pdf to xlsx", "pdf table to excel", "pdf spreadsheet converter"],
"ar": ["تحويل pdf إلى excel", "pdf إلى xlsx", "جدول pdf إلى excel"]
},
"benefit": {
"en": "Move tabular data out of PDF and into Excel so teams can filter, calculate, and reuse it.",
"ar": "انقل البيانات الجدولية من PDF إلى Excel حتى تتمكن الفرق من التصفية والحساب وإعادة الاستخدام."
},
"useCase": {
"en": "Helpful for invoices, statements, reports, and operations data.",
"ar": "مفيد للفواتير والكشوفات والتقارير وبيانات العمليات."
},
"relatedCollectionSlugs": ["pdf-converter-tools", "office-to-pdf-tools"]
},
{
"slug": "extract-tables-from-pdf",
"toolSlug": "extract-tables",
"category": "AI",
"focusKeyword": { "en": "extract tables from pdf", "ar": "استخراج الجداول من PDF" },
"supportingKeywords": {
"en": ["pdf table extractor", "capture tables from pdf", "pdf table to spreadsheet"],
"ar": ["استخراج الجداول من pdf", "أداة جداول pdf", "تحويل جدول pdf"]
},
"benefit": {
"en": "Pull structured tables from PDF pages when data needs to move into spreadsheets or analysis tools.",
"ar": "استخرج الجداول المنظمة من صفحات PDF عندما تحتاج البيانات إلى الانتقال إلى جداول البيانات أو أدوات التحليل."
},
"useCase": {
"en": "Useful for finance data, procurement sheets, and operational reporting.",
"ar": "مفيد للبيانات المالية وجداول المشتريات وتقارير العمليات."
},
"relatedCollectionSlugs": ["ai-document-tools", "pdf-converter-tools"]
},
{
"slug": "html-to-pdf-online",
"toolSlug": "html-to-pdf",
"category": "Convert",
"focusKeyword": { "en": "html to pdf online", "ar": "تحويل HTML إلى PDF أونلاين" },
"supportingKeywords": {
"en": ["convert html to pdf", "webpage to pdf", "html file to pdf"],
"ar": ["تحويل html إلى pdf", "صفحة ويب إلى pdf", "ملف html إلى pdf"]
},
"benefit": {
"en": "Capture web layouts as PDFs for sharing, approval, printing, or archiving.",
"ar": "التقط تنسيقات الويب كملفات PDF للمشاركة أو الاعتماد أو الطباعة أو الأرشفة."
},
"useCase": {
"en": "Helpful for invoices, landing page proofs, templates, and documentation exports.",
"ar": "مفيد للفواتير وإثباتات صفحات الهبوط والقوالب وتصدير الوثائق."
},
"relatedCollectionSlugs": ["convert-files-online", "office-to-pdf-tools"]
},
{
"slug": "scan-pdf-to-text",
"toolSlug": "ocr",
"category": "AI",
"focusKeyword": { "en": "scan pdf to text", "ar": "تحويل PDF الممسوح إلى نص" },
"supportingKeywords": {
"en": ["ocr scanned pdf", "scanned pdf text extraction", "scan to editable text"],
"ar": ["تحويل pdf الممسوح إلى نص", "ocr pdf ممسوح", "استخراج النص من pdf ممسوح"]
},
"benefit": {
"en": "Use OCR to recover editable text from scanned PDFs that would otherwise stay image-based.",
"ar": "استخدم OCR لاستعادة نص قابل للتحرير من ملفات PDF الممسوحة ضوئياً والتي كانت ستبقى معتمدة على الصور."
},
"useCase": {
"en": "Best for archive scans, old records, paperwork, and compliance files.",
"ar": "مناسب للأرشيفات الممسوحة والملفات القديمة والأوراق الإدارية وملفات الامتثال."
},
"relatedCollectionSlugs": ["scanned-document-tools", "ai-document-tools"]
},
{
"slug": "chat-with-pdf",
"toolSlug": "chat-pdf",
"category": "AI",
"focusKeyword": { "en": "chat with pdf", "ar": "الدردشة مع PDF" },
"supportingKeywords": {
"en": ["ask pdf questions", "ai pdf chat", "chat pdf online"],
"ar": ["الدردشة مع pdf", "سؤال pdf بالذكاء الاصطناعي", "chat pdf"]
},
"benefit": {
"en": "Ask direct questions about long PDF documents instead of manually searching page by page.",
"ar": "اسأل أسئلة مباشرة عن ملفات PDF الطويلة بدلاً من البحث اليدوي صفحةً صفحة."
},
"useCase": {
"en": "Useful for contracts, manuals, research papers, and policy reviews.",
"ar": "مفيد للعقود والأدلة وأوراق البحث ومراجعة السياسات."
},
"relatedCollectionSlugs": ["ai-document-tools", "scanned-document-tools"]
},
{
"slug": "summarize-pdf-online",
"toolSlug": "summarize-pdf",
"category": "AI",
"focusKeyword": { "en": "summarize pdf online", "ar": "تلخيص PDF أونلاين" },
"supportingKeywords": {
"en": ["pdf summary tool", "summarize document pdf", "ai pdf summary"],
"ar": ["تلخيص pdf أونلاين", "ملخص pdf", "تلخيص مستند pdf"]
},
"benefit": {
"en": "Extract the core points from long PDF files faster so review cycles and decision-making move sooner.",
"ar": "استخرج النقاط الأساسية من ملفات PDF الطويلة بسرعة أكبر حتى تتحرك دورات المراجعة واتخاذ القرار أسرع."
},
"useCase": {
"en": "Great for research, internal memos, reports, and customer documents.",
"ar": "ممتاز للبحث والمذكرات الداخلية والتقارير ووثائق العملاء."
},
"relatedCollectionSlugs": ["ai-document-tools", "best-pdf-tools"]
},
{
"slug": "translate-pdf-online",
"toolSlug": "translate-pdf",
"category": "AI",
"focusKeyword": { "en": "translate pdf online", "ar": "ترجمة PDF أونلاين" },
"supportingKeywords": {
"en": ["pdf translator online", "translate document pdf", "multilingual pdf translation"],
"ar": ["ترجمة pdf أونلاين", "مترجم pdf", "ترجمة مستند pdf"]
},
"benefit": {
"en": "Translate PDF content so multilingual teams can understand and share documents faster.",
"ar": "ترجم محتوى PDF حتى تتمكن الفرق متعددة اللغات من فهم المستندات ومشاركتها بسرعة أكبر."
},
"useCase": {
"en": "Useful for cross-border teams, customer support, procurement, and research.",
"ar": "مفيد للفرق العابرة للحدود ودعم العملاء والمشتريات والبحث."
},
"relatedCollectionSlugs": ["ai-document-tools", "arabic-pdf-tools"]
},
{
"slug": "convert-image-to-pdf",
"toolSlug": "images-to-pdf",
"category": "PDF",
"focusKeyword": { "en": "convert image to pdf", "ar": "تحويل الصورة إلى PDF" },
"supportingKeywords": {
"en": ["image to pdf converter", "photo to pdf online", "turn image into pdf"],
"ar": ["تحويل الصورة إلى pdf", "صورة إلى pdf", "تحويل الصور الى pdf"]
},
"benefit": {
"en": "Wrap image files in PDF format when the receiving system expects documents rather than photos.",
"ar": "حوّل ملفات الصور إلى صيغة PDF عندما يتوقع النظام المستقبل مستندات بدلاً من صور."
},
"useCase": {
"en": "Common for applications, government forms, receipts, and proof uploads.",
"ar": "شائع لطلبات التقديم والنماذج الحكومية والإيصالات ورفع ملفات الإثبات."
},
"relatedCollectionSlugs": ["image-to-pdf-tools", "convert-files-online"]
},
{
"slug": "convert-webp-to-jpg",
"toolSlug": "image-converter",
"category": "Image",
"focusKeyword": { "en": "convert webp to jpg", "ar": "تحويل WebP إلى JPG" },
"supportingKeywords": {
"en": ["webp to jpg online", "change webp to jpeg", "image format converter"],
"ar": ["تحويل webp إلى jpg", "webp إلى jpeg", "محول صيغ الصور"]
},
"benefit": {
"en": "Make WebP images compatible with apps, clients, and workflows that still expect JPG files.",
"ar": "اجعل صور WebP متوافقة مع التطبيقات والعملاء ومسارات العمل التي لا تزال تتوقع ملفات JPG."
},
"useCase": {
"en": "Useful for uploads, ecommerce operations, publishing, and legacy systems.",
"ar": "مفيد للرفع وعمليات التجارة الإلكترونية والنشر والأنظمة القديمة."
},
"relatedCollectionSlugs": ["online-image-tools", "convert-files-online"]
},
{
"slug": "resize-image-online",
"toolSlug": "image-resize",
"category": "Image",
"focusKeyword": { "en": "resize image online", "ar": "تغيير حجم الصورة أونلاين" },
"supportingKeywords": {
"en": ["image resizer online", "change image dimensions", "resize photo"],
"ar": ["تغيير حجم الصورة أونلاين", "مغير حجم الصورة", "تعديل أبعاد الصورة"]
},
"benefit": {
"en": "Adjust image dimensions quickly for upload requirements, web layouts, or marketplace listings.",
"ar": "عدّل أبعاد الصور بسرعة لمتطلبات الرفع أو تنسيقات الويب أو قوائم المتاجر."
},
"useCase": {
"en": "Useful for avatars, banners, product listings, and CMS uploads.",
"ar": "مفيد للصور الشخصية والبنرات وقوائم المنتجات ورفع ملفات أنظمة إدارة المحتوى."
},
"relatedCollectionSlugs": ["online-image-tools", "convert-files-online"]
},
{
"slug": "compress-image-online",
"toolSlug": "compress-image",
"category": "Image",
"focusKeyword": { "en": "compress image online", "ar": "ضغط الصورة أونلاين" },
"supportingKeywords": {
"en": ["reduce image size", "image compressor online", "shrink photo file"],
"ar": ["ضغط الصورة أونلاين", "تقليل حجم الصورة", "ضغط ملف الصورة"]
},
"benefit": {
"en": "Lower image file sizes for faster pages, smaller uploads, and easier sharing.",
"ar": "خفّض أحجام ملفات الصور لصفحات أسرع وملفات رفع أصغر ومشاركة أسهل."
},
"useCase": {
"en": "Useful for web publishing, product catalogs, forms, and mobile transfers.",
"ar": "مفيد للنشر على الويب وكتالوجات المنتجات والنماذج والنقل عبر الجوال."
},
"relatedCollectionSlugs": ["online-image-tools", "free-pdf-tools-online"]
},
{
"slug": "remove-image-background",
"toolSlug": "remove-background",
"category": "Image",
"focusKeyword": { "en": "remove image background", "ar": "إزالة خلفية الصورة" },
"supportingKeywords": {
"en": ["background remover online", "transparent background tool", "remove photo background"],
"ar": ["إزالة خلفية الصورة", "حذف خلفية الصورة", "أداة إزالة الخلفية"]
},
"benefit": {
"en": "Create transparent-background images quickly for storefronts, ads, and branded assets.",
"ar": "أنشئ صوراً بخلفية شفافة بسرعة للمتاجر والإعلانات والأصول ذات العلامة التجارية."
},
"useCase": {
"en": "Useful for ecommerce, presentations, catalog design, and social content.",
"ar": "مفيد للتجارة الإلكترونية والعروض وتصميم الكتالوجات والمحتوى الاجتماعي."
},
"relatedCollectionSlugs": ["online-image-tools", "convert-files-online"]
}
],
"collectionPageSeeds": [
{
"slug": "best-pdf-tools",
"focusKeyword": { "en": "best pdf tools", "ar": "أفضل أدوات PDF" },
"supportingKeywords": {
"en": ["online pdf toolkit", "top pdf tools", "document workflows"],
"ar": ["أفضل أدوات pdf", "مجموعة أدوات pdf", "أدوات المستندات"]
},
"introAngle": {
"en": "Group the highest-utility PDF workflows in one place so users can move from search intent to the right tool quickly.",
"ar": "اجمع أكثر مسارات PDF فائدة في مكان واحد حتى ينتقل المستخدم من نية البحث إلى الأداة المناسبة بسرعة."
},
"targetToolSlugs": ["pdf-to-word", "word-to-pdf", "compress-pdf", "merge-pdf", "split-pdf", "unlock-pdf"],
"relatedCollectionSlugs": ["free-pdf-tools-online", "pdf-converter-tools"]
},
{
"slug": "free-pdf-tools-online",
"focusKeyword": { "en": "free pdf tools online", "ar": "أدوات PDF مجانية أونلاين" },
"supportingKeywords": {
"en": ["free online pdf tools", "browser pdf utilities", "pdf tools without signup"],
"ar": ["أدوات pdf مجانية أونلاين", "أدوات pdf بدون تسجيل", "أدوات pdf من المتصفح"]
},
"introAngle": {
"en": "Capture users who want practical browser-based PDF work without downloads, subscriptions, or account setup.",
"ar": "استهدف المستخدمين الذين يريدون إنجاز أعمال PDF من المتصفح بدون تنزيلات أو اشتراكات أو إعداد حساب."
},
"targetToolSlugs": ["compress-pdf", "merge-pdf", "split-pdf", "unlock-pdf", "protect-pdf", "pdf-editor"],
"relatedCollectionSlugs": ["best-pdf-tools", "secure-pdf-tools"]
},
{
"slug": "convert-files-online",
"focusKeyword": { "en": "convert files online", "ar": "تحويل الملفات أونلاين" },
"supportingKeywords": {
"en": ["online file converter", "document conversion tools", "format converter online"],
"ar": ["تحويل الملفات أونلاين", "محول ملفات أونلاين", "أدوات تحويل الصيغ"]
},
"introAngle": {
"en": "Bring together the most common format changes across PDF, Office, images, and HTML in one discoverable page.",
"ar": "اجمع أكثر عمليات تغيير الصيغ شيوعاً عبر PDF وأوفيس والصور وHTML في صفحة واحدة قابلة للاكتشاف."
},
"targetToolSlugs": ["pdf-to-word", "word-to-pdf", "images-to-pdf", "image-converter", "html-to-pdf", "pdf-to-excel"],
"relatedCollectionSlugs": ["pdf-converter-tools", "online-image-tools"]
},
{
"slug": "pdf-converter-tools",
"focusKeyword": { "en": "pdf converter tools", "ar": "أدوات تحويل PDF" },
"supportingKeywords": {
"en": ["pdf conversion tools", "convert from pdf", "convert to pdf workflows"],
"ar": ["أدوات تحويل pdf", "تحويل من pdf", "التحويل إلى pdf"]
},
"introAngle": {
"en": "Capture conversion-intent traffic around moving content between PDF and editable, shareable, or image-based formats.",
"ar": "استهدف ترافيك نية التحويل حول نقل المحتوى بين PDF والصيغ القابلة للتحرير أو المشاركة أو المعتمدة على الصور."
},
"targetToolSlugs": ["pdf-to-word", "word-to-pdf", "pdf-to-excel", "pdf-to-images", "images-to-pdf", "html-to-pdf"],
"relatedCollectionSlugs": ["convert-files-online", "office-to-pdf-tools"]
},
{
"slug": "secure-pdf-tools",
"focusKeyword": { "en": "secure pdf tools", "ar": "أدوات تأمين PDF" },
"supportingKeywords": {
"en": ["pdf security tools", "protect and unlock pdf", "pdf permission workflows"],
"ar": ["أدوات تأمين pdf", "حماية وفتح pdf", "صلاحيات pdf"]
},
"introAngle": {
"en": "Cover the workflows people search when documents need access control, branding, or safer circulation.",
"ar": "غطِ مسارات العمل التي يبحث عنها المستخدمون عندما تحتاج المستندات إلى التحكم في الوصول أو العلامة التجارية أو التوزيع الآمن."
},
"targetToolSlugs": ["protect-pdf", "unlock-pdf", "watermark-pdf", "remove-watermark-pdf", "compress-pdf", "merge-pdf"],
"relatedCollectionSlugs": ["best-pdf-tools", "free-pdf-tools-online"]
},
{
"slug": "ai-document-tools",
"focusKeyword": { "en": "ai document tools", "ar": "أدوات المستندات بالذكاء الاصطناعي" },
"supportingKeywords": {
"en": ["ai pdf tools", "smart document workflows", "document ai online"],
"ar": ["أدوات pdf بالذكاء الاصطناعي", "أدوات مستندات ذكية", "ذكاء اصطناعي للمستندات"]
},
"introAngle": {
"en": "Group AI-assisted document workflows for question answering, OCR, translation, table extraction, and summarization.",
"ar": "اجمع مسارات المستندات المدعومة بالذكاء الاصطناعي للأسئلة وOCR والترجمة واستخراج الجداول والتلخيص."
},
"targetToolSlugs": ["chat-pdf", "summarize-pdf", "translate-pdf", "ocr", "extract-tables", "pdf-flowchart"],
"relatedCollectionSlugs": ["scanned-document-tools", "arabic-pdf-tools"]
},
{
"slug": "image-to-pdf-tools",
"focusKeyword": { "en": "image to pdf tools", "ar": "أدوات تحويل الصور إلى PDF" },
"supportingKeywords": {
"en": ["images into pdf", "photo to pdf workflows", "scan images to pdf"],
"ar": ["تحويل الصور إلى pdf", "صورة إلى pdf", "أدوات صور إلى pdf"]
},
"introAngle": {
"en": "Target users who start with image files but need a document-friendly PDF result for submission or storage.",
"ar": "استهدف المستخدمين الذين يبدأون بملفات صور لكنهم يحتاجون نتيجة PDF مناسبة للتقديم أو التخزين."
},
"targetToolSlugs": ["images-to-pdf", "pdf-to-images", "image-resize", "compress-image", "remove-background", "image-converter"],
"relatedCollectionSlugs": ["online-image-tools", "convert-files-online"]
},
{
"slug": "online-image-tools",
"focusKeyword": { "en": "online image tools", "ar": "أدوات الصور أونلاين" },
"supportingKeywords": {
"en": ["browser image tools", "image editing tools online", "online photo utilities"],
"ar": ["أدوات الصور أونلاين", "أدوات تعديل الصور", "أدوات الصور من المتصفح"]
},
"introAngle": {
"en": "Group lightweight image workflows for format changes, compression, resizing, cleanup, and PDF handoff.",
"ar": "اجمع مسارات الصور الخفيفة لتغيير الصيغ والضغط وتغيير الحجم والتنظيف والتمرير إلى PDF."
},
"targetToolSlugs": ["image-converter", "image-resize", "compress-image", "remove-background", "images-to-pdf", "image-crop"],
"relatedCollectionSlugs": ["image-to-pdf-tools", "convert-files-online"]
},
{
"slug": "office-to-pdf-tools",
"focusKeyword": { "en": "office to pdf tools", "ar": "أدوات تحويل ملفات أوفيس إلى PDF" },
"supportingKeywords": {
"en": ["word excel powerpoint to pdf", "office document pdf conversion", "export office files to pdf"],
"ar": ["تحويل ملفات أوفيس إلى pdf", "word excel powerpoint إلى pdf", "تصدير ملفات أوفيس إلى pdf"]
},
"introAngle": {
"en": "Focus on workflows where teams convert Office documents into portable PDF files for sharing or approval.",
"ar": "ركّز على المسارات التي تحول فيها الفرق ملفات أوفيس إلى PDF قابل للنقل للمشاركة أو الاعتماد."
},
"targetToolSlugs": ["word-to-pdf", "excel-to-pdf", "pptx-to-pdf", "html-to-pdf", "sign-pdf", "pdf-editor"],
"relatedCollectionSlugs": ["convert-files-online", "pdf-converter-tools"]
},
{
"slug": "scanned-document-tools",
"focusKeyword": { "en": "scanned document tools", "ar": "أدوات المستندات الممسوحة ضوئياً" },
"supportingKeywords": {
"en": ["scan to text tools", "ocr pdf tools", "scan document workflows"],
"ar": ["أدوات المستندات الممسوحة", "ocr للمستندات", "مسارات المستندات الممسوحة"]
},
"introAngle": {
"en": "Capture users who need OCR, cleanup, compression, and reuse workflows for image-heavy or scanned files.",
"ar": "استهدف المستخدمين الذين يحتاجون إلى OCR والتنظيف والضغط وإعادة الاستخدام للملفات الممسوحة أو المعتمدة على الصور."
},
"targetToolSlugs": ["ocr", "compress-pdf", "pdf-to-word", "extract-tables", "rotate-pdf", "pdf-to-images"],
"relatedCollectionSlugs": ["ai-document-tools", "arabic-pdf-tools"]
},
{
"slug": "arabic-pdf-tools",
"focusKeyword": { "en": "arabic pdf tools", "ar": "أدوات PDF العربية" },
"supportingKeywords": {
"en": ["pdf tools for arabic documents", "arabic document workflows", "rtl pdf tools"],
"ar": ["أدوات pdf العربية", "أدوات للمستندات العربية", "pdf للغة العربية"]
},
"introAngle": {
"en": "Position Dociva for Arabic-language document workflows where RTL support and bilingual search intent matter.",
"ar": "ضع Dociva في موقع قوي لمسارات المستندات العربية حيث يكون دعم RTL ونية البحث ثنائية اللغة مهمين."
},
"targetToolSlugs": ["pdf-to-word", "word-to-pdf", "ocr", "translate-pdf", "images-to-pdf", "compress-pdf"],
"relatedCollectionSlugs": ["ai-document-tools", "best-pdf-tools"]
}
]
}

View File

@@ -0,0 +1,30 @@
import { describe, expect, it } from 'vitest';
import {
PROGRAMMATIC_TOOL_PAGES,
SEO_COLLECTION_PAGES,
SEO_TOTAL_PAGE_COUNT,
getLocalizedSeoLandingPaths,
} from '@/seo/seoData';
describe('SEO data engine', () => {
it('generates at least 50 bilingual SEO pages', () => {
expect(SEO_TOTAL_PAGE_COUNT).toBeGreaterThanOrEqual(50);
});
it('has no duplicate english slugs', () => {
const englishPaths = getLocalizedSeoLandingPaths('en');
expect(new Set(englishPaths).size).toBe(englishPaths.length);
});
it('generates matching arabic localized paths', () => {
const englishPaths = getLocalizedSeoLandingPaths('en');
const arabicPaths = getLocalizedSeoLandingPaths('ar');
expect(arabicPaths.length).toBe(englishPaths.length);
expect(arabicPaths.every((path) => path.startsWith('/ar/'))).toBe(true);
});
it('keeps both tool and collection SEO inventories populated', () => {
expect(PROGRAMMATIC_TOOL_PAGES.length).toBeGreaterThan(30);
expect(SEO_COLLECTION_PAGES.length).toBeGreaterThanOrEqual(10);
});
});

187
frontend/src/seo/seoData.ts Normal file
View File

@@ -0,0 +1,187 @@
import seoSeedConfig from '@/seo/seoData.json';
import type {
LocalizedText,
LocalizedTextList,
ProgrammaticToolPage,
SeoCollectionPage,
SeoFaqTemplate,
SeoLocale,
} from '@/config/seoPages';
interface ToolPageSeed {
slug: string;
toolSlug: string;
category: 'PDF' | 'Image' | 'AI' | 'Convert' | 'Utility';
focusKeyword: LocalizedText;
supportingKeywords: LocalizedTextList;
benefit: LocalizedText;
useCase: LocalizedText;
relatedCollectionSlugs: string[];
}
interface CollectionPageSeed {
slug: string;
focusKeyword: LocalizedText;
supportingKeywords: LocalizedTextList;
introAngle: LocalizedText;
targetToolSlugs: string[];
relatedCollectionSlugs: string[];
}
interface SeoSeedConfig {
toolPageSeeds: ToolPageSeed[];
collectionPageSeeds: CollectionPageSeed[];
}
const seedConfig = seoSeedConfig as SeoSeedConfig;
function buildToolFaqs(seed: ToolPageSeed): SeoFaqTemplate[] {
return [
{
question: {
en: `When should I use ${seed.focusKeyword.en}?`,
ar: `متى أستخدم ${seed.focusKeyword.ar}؟`,
},
answer: {
en: `${seed.useCase.en} ${seed.benefit.en}`,
ar: `${seed.useCase.ar} ${seed.benefit.ar}`,
},
},
{
question: {
en: `What makes ${seed.focusKeyword.en} useful online?`,
ar: `ما الذي يجعل ${seed.focusKeyword.ar} مفيداً أونلاين؟`,
},
answer: {
en: `Dociva helps you handle this workflow in the browser with secure processing, fast output, and no installation. ${seed.benefit.en}`,
ar: `يساعدك Dociva على تنفيذ هذا المسار من المتصفح مع معالجة آمنة ونتيجة سريعة وبدون تثبيت. ${seed.benefit.ar}`,
},
},
];
}
function buildCollectionFaqs(seed: CollectionPageSeed): SeoFaqTemplate[] {
return [
{
question: {
en: `What is included in ${seed.focusKeyword.en}?`,
ar: `ماذا تتضمن ${seed.focusKeyword.ar}؟`,
},
answer: {
en: `${seed.introAngle.en} This page brings together the main workflows users usually need before downloading, sharing, or archiving files.`,
ar: `${seed.introAngle.ar} تجمع هذه الصفحة أهم المسارات التي يحتاجها المستخدمون عادة قبل التنزيل أو المشاركة أو الأرشفة.`,
},
},
{
question: {
en: `How do I choose the right workflow from ${seed.focusKeyword.en}?`,
ar: `كيف أختار المسار المناسب من ${seed.focusKeyword.ar}؟`,
},
answer: {
en: `Start with the outcome you need, then open the matching tool. This collection is designed to reduce guesswork and move directly into execution.`,
ar: `ابدأ بالنتيجة التي تحتاجها ثم افتح الأداة المطابقة. صُممت هذه المجموعة لتقليل التخمين والانتقال مباشرة إلى التنفيذ.`,
},
},
];
}
function buildToolSections(seed: ToolPageSeed): Array<{ heading: LocalizedText; body: LocalizedText }> {
return [
{
heading: {
en: `Why people search for ${seed.focusKeyword.en}`,
ar: `لماذا يبحث المستخدمون عن ${seed.focusKeyword.ar}`,
},
body: {
en: seed.benefit.en,
ar: seed.benefit.ar,
},
},
{
heading: {
en: 'Common use cases',
ar: 'حالات الاستخدام الشائعة',
},
body: {
en: seed.useCase.en,
ar: seed.useCase.ar,
},
},
];
}
function buildCollectionSections(seed: CollectionPageSeed): Array<{ heading: LocalizedText; body: LocalizedText }> {
return [
{
heading: {
en: `What this ${seed.focusKeyword.en} page covers`,
ar: `ما الذي تغطيه صفحة ${seed.focusKeyword.ar}`,
},
body: {
en: seed.introAngle.en,
ar: seed.introAngle.ar,
},
},
{
heading: {
en: 'How to use this collection',
ar: 'كيفية استخدام هذه المجموعة',
},
body: {
en: 'Choose the workflow that matches the output you need first, then chain cleanup, security, or AI tools only when the file requires them.',
ar: 'اختر أولاً مسار العمل الذي يطابق النتيجة التي تحتاجها، ثم أضف أدوات التنظيف أو الأمان أو الذكاء الاصطناعي فقط عندما يتطلب الملف ذلك.',
},
},
];
}
export const PROGRAMMATIC_TOOL_PAGES: ProgrammaticToolPage[] = seedConfig.toolPageSeeds.map((seed) => ({
slug: seed.slug,
toolSlug: seed.toolSlug,
category: seed.category,
focusKeyword: seed.focusKeyword,
supportingKeywords: seed.supportingKeywords,
titleTemplate: {
en: `{{focusKeyword}} online | {{brand}}`,
ar: `{{focusKeyword}} أونلاين | {{brand}}`,
},
descriptionTemplate: {
en: `${seed.benefit.en} ${seed.useCase.en} Use {{brand}} to complete this workflow online with no signup required.`,
ar: `${seed.benefit.ar} ${seed.useCase.ar} استخدم {{brand}} لإتمام هذا المسار أونلاين بدون تسجيل.`,
},
faqTemplates: buildToolFaqs(seed),
relatedCollectionSlugs: seed.relatedCollectionSlugs,
contentSections: buildToolSections(seed),
}));
export const SEO_COLLECTION_PAGES: SeoCollectionPage[] = seedConfig.collectionPageSeeds.map((seed) => ({
slug: seed.slug,
focusKeyword: seed.focusKeyword,
supportingKeywords: seed.supportingKeywords,
titleTemplate: {
en: `{{focusKeyword}} | {{brand}}`,
ar: `{{focusKeyword}} | {{brand}}`,
},
descriptionTemplate: {
en: `${seed.introAngle.en} Browse the most relevant workflows in one focused landing page.`,
ar: `${seed.introAngle.ar} تصفح أكثر المسارات صلة في صفحة هبوط واحدة مركزة.`,
},
introTemplate: {
en: seed.introAngle.en,
ar: seed.introAngle.ar,
},
targetToolSlugs: seed.targetToolSlugs,
faqTemplates: buildCollectionFaqs(seed),
relatedCollectionSlugs: seed.relatedCollectionSlugs,
contentSections: buildCollectionSections(seed),
}));
export const SEO_TOTAL_PAGE_COUNT = PROGRAMMATIC_TOOL_PAGES.length + SEO_COLLECTION_PAGES.length;
export function getLocalizedSeoLandingPaths(locale: SeoLocale): string[] {
const prefix = locale === 'ar' ? '/ar' : '';
return [
...PROGRAMMATIC_TOOL_PAGES.map((page) => `${prefix}/${page.slug}`),
...SEO_COLLECTION_PAGES.map((page) => `${prefix}/${page.slug}`),
];
}